| //===- ExecutionDomainFix.cpp - Fix execution domain issues ----*- C++ -*--===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/CodeGen/ExecutionDomainFix.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/TargetInstrInfo.h" |
| |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "execution-deps-fix" |
| |
| iterator_range<SmallVectorImpl<int>::const_iterator> |
| ExecutionDomainFix::regIndices(unsigned Reg) const { |
| assert(Reg < AliasMap.size() && "Invalid register"); |
| const auto &Entry = AliasMap[Reg]; |
| return make_range(Entry.begin(), Entry.end()); |
| } |
| |
| DomainValue *ExecutionDomainFix::alloc(int domain) { |
| DomainValue *dv = Avail.empty() ? new (Allocator.Allocate()) DomainValue |
| : Avail.pop_back_val(); |
| if (domain >= 0) |
| dv->addDomain(domain); |
| assert(dv->Refs == 0 && "Reference count wasn't cleared"); |
| assert(!dv->Next && "Chained DomainValue shouldn't have been recycled"); |
| return dv; |
| } |
| |
| void ExecutionDomainFix::release(DomainValue *DV) { |
| while (DV) { |
| assert(DV->Refs && "Bad DomainValue"); |
| if (--DV->Refs) |
| return; |
| |
| // There are no more DV references. Collapse any contained instructions. |
| if (DV->AvailableDomains && !DV->isCollapsed()) |
| collapse(DV, DV->getFirstDomain()); |
| |
| DomainValue *Next = DV->Next; |
| DV->clear(); |
| Avail.push_back(DV); |
| // Also release the next DomainValue in the chain. |
| DV = Next; |
| } |
| } |
| |
| DomainValue *ExecutionDomainFix::resolve(DomainValue *&DVRef) { |
| DomainValue *DV = DVRef; |
| if (!DV || !DV->Next) |
| return DV; |
| |
| // DV has a chain. Find the end. |
| do |
| DV = DV->Next; |
| while (DV->Next); |
| |
| // Update DVRef to point to DV. |
| retain(DV); |
| release(DVRef); |
| DVRef = DV; |
| return DV; |
| } |
| |
| void ExecutionDomainFix::setLiveReg(int rx, DomainValue *dv) { |
| assert(unsigned(rx) < NumRegs && "Invalid index"); |
| assert(!LiveRegs.empty() && "Must enter basic block first."); |
| |
| if (LiveRegs[rx] == dv) |
| return; |
| if (LiveRegs[rx]) |
| release(LiveRegs[rx]); |
| LiveRegs[rx] = retain(dv); |
| } |
| |
| void ExecutionDomainFix::kill(int rx) { |
| assert(unsigned(rx) < NumRegs && "Invalid index"); |
| assert(!LiveRegs.empty() && "Must enter basic block first."); |
| if (!LiveRegs[rx]) |
| return; |
| |
| release(LiveRegs[rx]); |
| LiveRegs[rx] = nullptr; |
| } |
| |
| void ExecutionDomainFix::force(int rx, unsigned domain) { |
| assert(unsigned(rx) < NumRegs && "Invalid index"); |
| assert(!LiveRegs.empty() && "Must enter basic block first."); |
| if (DomainValue *dv = LiveRegs[rx]) { |
| if (dv->isCollapsed()) |
| dv->addDomain(domain); |
| else if (dv->hasDomain(domain)) |
| collapse(dv, domain); |
| else { |
| // This is an incompatible open DomainValue. Collapse it to whatever and |
| // force the new value into domain. This costs a domain crossing. |
| collapse(dv, dv->getFirstDomain()); |
| assert(LiveRegs[rx] && "Not live after collapse?"); |
| LiveRegs[rx]->addDomain(domain); |
| } |
| } else { |
| // Set up basic collapsed DomainValue. |
| setLiveReg(rx, alloc(domain)); |
| } |
| } |
| |
| void ExecutionDomainFix::collapse(DomainValue *dv, unsigned domain) { |
| assert(dv->hasDomain(domain) && "Cannot collapse"); |
| |
| // Collapse all the instructions. |
| while (!dv->Instrs.empty()) |
| TII->setExecutionDomain(*dv->Instrs.pop_back_val(), domain); |
| dv->setSingleDomain(domain); |
| |
| // If there are multiple users, give them new, unique DomainValues. |
| if (!LiveRegs.empty() && dv->Refs > 1) |
| for (unsigned rx = 0; rx != NumRegs; ++rx) |
| if (LiveRegs[rx] == dv) |
| setLiveReg(rx, alloc(domain)); |
| } |
| |
| bool ExecutionDomainFix::merge(DomainValue *A, DomainValue *B) { |
| assert(!A->isCollapsed() && "Cannot merge into collapsed"); |
| assert(!B->isCollapsed() && "Cannot merge from collapsed"); |
| if (A == B) |
| return true; |
| // Restrict to the domains that A and B have in common. |
| unsigned common = A->getCommonDomains(B->AvailableDomains); |
| if (!common) |
| return false; |
| A->AvailableDomains = common; |
| A->Instrs.append(B->Instrs.begin(), B->Instrs.end()); |
| |
| // Clear the old DomainValue so we won't try to swizzle instructions twice. |
| B->clear(); |
| // All uses of B are referred to A. |
| B->Next = retain(A); |
| |
| for (unsigned rx = 0; rx != NumRegs; ++rx) { |
| assert(!LiveRegs.empty() && "no space allocated for live registers"); |
| if (LiveRegs[rx] == B) |
| setLiveReg(rx, A); |
| } |
| return true; |
| } |
| |
| void ExecutionDomainFix::enterBasicBlock( |
| const LoopTraversal::TraversedMBBInfo &TraversedMBB) { |
| |
| MachineBasicBlock *MBB = TraversedMBB.MBB; |
| |
| // Set up LiveRegs to represent registers entering MBB. |
| // Set default domain values to 'no domain' (nullptr) |
| if (LiveRegs.empty()) |
| LiveRegs.assign(NumRegs, nullptr); |
| |
| // This is the entry block. |
| if (MBB->pred_empty()) { |
| LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << ": entry\n"); |
| return; |
| } |
| |
| // Try to coalesce live-out registers from predecessors. |
| for (MachineBasicBlock *pred : MBB->predecessors()) { |
| assert(unsigned(pred->getNumber()) < MBBOutRegsInfos.size() && |
| "Should have pre-allocated MBBInfos for all MBBs"); |
| LiveRegsDVInfo &Incoming = MBBOutRegsInfos[pred->getNumber()]; |
| // Incoming is null if this is a backedge from a BB |
| // we haven't processed yet |
| if (Incoming.empty()) |
| continue; |
| |
| for (unsigned rx = 0; rx != NumRegs; ++rx) { |
| DomainValue *pdv = resolve(Incoming[rx]); |
| if (!pdv) |
| continue; |
| if (!LiveRegs[rx]) { |
| setLiveReg(rx, pdv); |
| continue; |
| } |
| |
| // We have a live DomainValue from more than one predecessor. |
| if (LiveRegs[rx]->isCollapsed()) { |
| // We are already collapsed, but predecessor is not. Force it. |
| unsigned Domain = LiveRegs[rx]->getFirstDomain(); |
| if (!pdv->isCollapsed() && pdv->hasDomain(Domain)) |
| collapse(pdv, Domain); |
| continue; |
| } |
| |
| // Currently open, merge in predecessor. |
| if (!pdv->isCollapsed()) |
| merge(LiveRegs[rx], pdv); |
| else |
| force(rx, pdv->getFirstDomain()); |
| } |
| } |
| LLVM_DEBUG(dbgs() << printMBBReference(*MBB) |
| << (!TraversedMBB.IsDone ? ": incomplete\n" |
| : ": all preds known\n")); |
| } |
| |
| void ExecutionDomainFix::leaveBasicBlock( |
| const LoopTraversal::TraversedMBBInfo &TraversedMBB) { |
| assert(!LiveRegs.empty() && "Must enter basic block first."); |
| unsigned MBBNumber = TraversedMBB.MBB->getNumber(); |
| assert(MBBNumber < MBBOutRegsInfos.size() && |
| "Unexpected basic block number."); |
| // Save register clearances at end of MBB - used by enterBasicBlock(). |
| for (DomainValue *OldLiveReg : MBBOutRegsInfos[MBBNumber]) { |
| release(OldLiveReg); |
| } |
| MBBOutRegsInfos[MBBNumber] = LiveRegs; |
| LiveRegs.clear(); |
| } |
| |
| bool ExecutionDomainFix::visitInstr(MachineInstr *MI) { |
| // Update instructions with explicit execution domains. |
| std::pair<uint16_t, uint16_t> DomP = TII->getExecutionDomain(*MI); |
| if (DomP.first) { |
| if (DomP.second) |
| visitSoftInstr(MI, DomP.second); |
| else |
| visitHardInstr(MI, DomP.first); |
| } |
| |
| return !DomP.first; |
| } |
| |
| void ExecutionDomainFix::processDefs(MachineInstr *MI, bool Kill) { |
| assert(!MI->isDebugInstr() && "Won't process debug values"); |
| const MCInstrDesc &MCID = MI->getDesc(); |
| for (unsigned i = 0, |
| e = MI->isVariadic() ? MI->getNumOperands() : MCID.getNumDefs(); |
| i != e; ++i) { |
| MachineOperand &MO = MI->getOperand(i); |
| if (!MO.isReg()) |
| continue; |
| if (MO.isUse()) |
| continue; |
| for (int rx : regIndices(MO.getReg())) { |
| // This instruction explicitly defines rx. |
| LLVM_DEBUG(dbgs() << printReg(RC->getRegister(rx), TRI) << ":\t" << *MI); |
| |
| // Kill off domains redefined by generic instructions. |
| if (Kill) |
| kill(rx); |
| } |
| } |
| } |
| |
| void ExecutionDomainFix::visitHardInstr(MachineInstr *mi, unsigned domain) { |
| // Collapse all uses. |
| for (unsigned i = mi->getDesc().getNumDefs(), |
| e = mi->getDesc().getNumOperands(); |
| i != e; ++i) { |
| MachineOperand &mo = mi->getOperand(i); |
| if (!mo.isReg()) |
| continue; |
| for (int rx : regIndices(mo.getReg())) { |
| force(rx, domain); |
| } |
| } |
| |
| // Kill all defs and force them. |
| for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) { |
| MachineOperand &mo = mi->getOperand(i); |
| if (!mo.isReg()) |
| continue; |
| for (int rx : regIndices(mo.getReg())) { |
| kill(rx); |
| force(rx, domain); |
| } |
| } |
| } |
| |
| void ExecutionDomainFix::visitSoftInstr(MachineInstr *mi, unsigned mask) { |
| // Bitmask of available domains for this instruction after taking collapsed |
| // operands into account. |
| unsigned available = mask; |
| |
| // Scan the explicit use operands for incoming domains. |
| SmallVector<int, 4> used; |
| if (!LiveRegs.empty()) |
| for (unsigned i = mi->getDesc().getNumDefs(), |
| e = mi->getDesc().getNumOperands(); |
| i != e; ++i) { |
| MachineOperand &mo = mi->getOperand(i); |
| if (!mo.isReg()) |
| continue; |
| for (int rx : regIndices(mo.getReg())) { |
| DomainValue *dv = LiveRegs[rx]; |
| if (dv == nullptr) |
| continue; |
| // Bitmask of domains that dv and available have in common. |
| unsigned common = dv->getCommonDomains(available); |
| // Is it possible to use this collapsed register for free? |
| if (dv->isCollapsed()) { |
| // Restrict available domains to the ones in common with the operand. |
| // If there are no common domains, we must pay the cross-domain |
| // penalty for this operand. |
| if (common) |
| available = common; |
| } else if (common) |
| // Open DomainValue is compatible, save it for merging. |
| used.push_back(rx); |
| else |
| // Open DomainValue is not compatible with instruction. It is useless |
| // now. |
| kill(rx); |
| } |
| } |
| |
| // If the collapsed operands force a single domain, propagate the collapse. |
| if (isPowerOf2_32(available)) { |
| unsigned domain = countTrailingZeros(available); |
| TII->setExecutionDomain(*mi, domain); |
| visitHardInstr(mi, domain); |
| return; |
| } |
| |
| // Kill off any remaining uses that don't match available, and build a list of |
| // incoming DomainValues that we want to merge. |
| SmallVector<int, 4> Regs; |
| for (int rx : used) { |
| assert(!LiveRegs.empty() && "no space allocated for live registers"); |
| DomainValue *&LR = LiveRegs[rx]; |
| // This useless DomainValue could have been missed above. |
| if (!LR->getCommonDomains(available)) { |
| kill(rx); |
| continue; |
| } |
| // Sorted insertion. |
| // Enables giving priority to the latest domains during merging. |
| auto I = std::upper_bound( |
| Regs.begin(), Regs.end(), rx, [&](int LHS, const int RHS) { |
| return RDA->getReachingDef(mi, RC->getRegister(LHS)) < |
| RDA->getReachingDef(mi, RC->getRegister(RHS)); |
| }); |
| Regs.insert(I, rx); |
| } |
| |
| // doms are now sorted in order of appearance. Try to merge them all, giving |
| // priority to the latest ones. |
| DomainValue *dv = nullptr; |
| while (!Regs.empty()) { |
| if (!dv) { |
| dv = LiveRegs[Regs.pop_back_val()]; |
| // Force the first dv to match the current instruction. |
| dv->AvailableDomains = dv->getCommonDomains(available); |
| assert(dv->AvailableDomains && "Domain should have been filtered"); |
| continue; |
| } |
| |
| DomainValue *Latest = LiveRegs[Regs.pop_back_val()]; |
| // Skip already merged values. |
| if (Latest == dv || Latest->Next) |
| continue; |
| if (merge(dv, Latest)) |
| continue; |
| |
| // If latest didn't merge, it is useless now. Kill all registers using it. |
| for (int i : used) { |
| assert(!LiveRegs.empty() && "no space allocated for live registers"); |
| if (LiveRegs[i] == Latest) |
| kill(i); |
| } |
| } |
| |
| // dv is the DomainValue we are going to use for this instruction. |
| if (!dv) { |
| dv = alloc(); |
| dv->AvailableDomains = available; |
| } |
| dv->Instrs.push_back(mi); |
| |
| // Finally set all defs and non-collapsed uses to dv. We must iterate through |
| // all the operators, including imp-def ones. |
| for (MachineOperand &mo : mi->operands()) { |
| if (!mo.isReg()) |
| continue; |
| for (int rx : regIndices(mo.getReg())) { |
| if (!LiveRegs[rx] || (mo.isDef() && LiveRegs[rx] != dv)) { |
| kill(rx); |
| setLiveReg(rx, dv); |
| } |
| } |
| } |
| } |
| |
| void ExecutionDomainFix::processBasicBlock( |
| const LoopTraversal::TraversedMBBInfo &TraversedMBB) { |
| enterBasicBlock(TraversedMBB); |
| // If this block is not done, it makes little sense to make any decisions |
| // based on clearance information. We need to make a second pass anyway, |
| // and by then we'll have better information, so we can avoid doing the work |
| // to try and break dependencies now. |
| for (MachineInstr &MI : *TraversedMBB.MBB) { |
| if (!MI.isDebugInstr()) { |
| bool Kill = false; |
| if (TraversedMBB.PrimaryPass) |
| Kill = visitInstr(&MI); |
| processDefs(&MI, Kill); |
| } |
| } |
| leaveBasicBlock(TraversedMBB); |
| } |
| |
| bool ExecutionDomainFix::runOnMachineFunction(MachineFunction &mf) { |
| if (skipFunction(mf.getFunction())) |
| return false; |
| MF = &mf; |
| TII = MF->getSubtarget().getInstrInfo(); |
| TRI = MF->getSubtarget().getRegisterInfo(); |
| LiveRegs.clear(); |
| assert(NumRegs == RC->getNumRegs() && "Bad regclass"); |
| |
| LLVM_DEBUG(dbgs() << "********** FIX EXECUTION DOMAIN: " |
| << TRI->getRegClassName(RC) << " **********\n"); |
| |
| // If no relevant registers are used in the function, we can skip it |
| // completely. |
| bool anyregs = false; |
| const MachineRegisterInfo &MRI = mf.getRegInfo(); |
| for (unsigned Reg : *RC) { |
| if (MRI.isPhysRegUsed(Reg)) { |
| anyregs = true; |
| break; |
| } |
| } |
| if (!anyregs) |
| return false; |
| |
| RDA = &getAnalysis<ReachingDefAnalysis>(); |
| |
| // Initialize the AliasMap on the first use. |
| if (AliasMap.empty()) { |
| // Given a PhysReg, AliasMap[PhysReg] returns a list of indices into RC and |
| // therefore the LiveRegs array. |
| AliasMap.resize(TRI->getNumRegs()); |
| for (unsigned i = 0, e = RC->getNumRegs(); i != e; ++i) |
| for (MCRegAliasIterator AI(RC->getRegister(i), TRI, true); AI.isValid(); |
| ++AI) |
| AliasMap[*AI].push_back(i); |
| } |
| |
| // Initialize the MBBOutRegsInfos |
| MBBOutRegsInfos.resize(mf.getNumBlockIDs()); |
| |
| // Traverse the basic blocks. |
| LoopTraversal Traversal; |
| LoopTraversal::TraversalOrder TraversedMBBOrder = Traversal.traverse(mf); |
| for (LoopTraversal::TraversedMBBInfo TraversedMBB : TraversedMBBOrder) { |
| processBasicBlock(TraversedMBB); |
| } |
| |
| for (LiveRegsDVInfo OutLiveRegs : MBBOutRegsInfos) { |
| for (DomainValue *OutLiveReg : OutLiveRegs) { |
| if (OutLiveReg) |
| release(OutLiveReg); |
| } |
| } |
| MBBOutRegsInfos.clear(); |
| Avail.clear(); |
| Allocator.DestroyAll(); |
| |
| return false; |
| } |