Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/ExecutionDomainFix.cpp
35232 views
//===- ExecutionDomainFix.cpp - Fix execution domain issues ----*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/CodeGen/ExecutionDomainFix.h"9#include "llvm/CodeGen/MachineRegisterInfo.h"10#include "llvm/CodeGen/TargetInstrInfo.h"11#include "llvm/Support/Debug.h"1213using namespace llvm;1415#define DEBUG_TYPE "execution-deps-fix"1617iterator_range<SmallVectorImpl<int>::const_iterator>18ExecutionDomainFix::regIndices(unsigned Reg) const {19assert(Reg < AliasMap.size() && "Invalid register");20const auto &Entry = AliasMap[Reg];21return make_range(Entry.begin(), Entry.end());22}2324DomainValue *ExecutionDomainFix::alloc(int domain) {25DomainValue *dv = Avail.empty() ? new (Allocator.Allocate()) DomainValue26: Avail.pop_back_val();27if (domain >= 0)28dv->addDomain(domain);29assert(dv->Refs == 0 && "Reference count wasn't cleared");30assert(!dv->Next && "Chained DomainValue shouldn't have been recycled");31return dv;32}3334void ExecutionDomainFix::release(DomainValue *DV) {35while (DV) {36assert(DV->Refs && "Bad DomainValue");37if (--DV->Refs)38return;3940// There are no more DV references. Collapse any contained instructions.41if (DV->AvailableDomains && !DV->isCollapsed())42collapse(DV, DV->getFirstDomain());4344DomainValue *Next = DV->Next;45DV->clear();46Avail.push_back(DV);47// Also release the next DomainValue in the chain.48DV = Next;49}50}5152DomainValue *ExecutionDomainFix::resolve(DomainValue *&DVRef) {53DomainValue *DV = DVRef;54if (!DV || !DV->Next)55return DV;5657// DV has a chain. Find the end.58do59DV = DV->Next;60while (DV->Next);6162// Update DVRef to point to DV.63retain(DV);64release(DVRef);65DVRef = DV;66return DV;67}6869void ExecutionDomainFix::setLiveReg(int rx, DomainValue *dv) {70assert(unsigned(rx) < NumRegs && "Invalid index");71assert(!LiveRegs.empty() && "Must enter basic block first.");7273if (LiveRegs[rx] == dv)74return;75if (LiveRegs[rx])76release(LiveRegs[rx]);77LiveRegs[rx] = retain(dv);78}7980void ExecutionDomainFix::kill(int rx) {81assert(unsigned(rx) < NumRegs && "Invalid index");82assert(!LiveRegs.empty() && "Must enter basic block first.");83if (!LiveRegs[rx])84return;8586release(LiveRegs[rx]);87LiveRegs[rx] = nullptr;88}8990void ExecutionDomainFix::force(int rx, unsigned domain) {91assert(unsigned(rx) < NumRegs && "Invalid index");92assert(!LiveRegs.empty() && "Must enter basic block first.");93if (DomainValue *dv = LiveRegs[rx]) {94if (dv->isCollapsed())95dv->addDomain(domain);96else if (dv->hasDomain(domain))97collapse(dv, domain);98else {99// This is an incompatible open DomainValue. Collapse it to whatever and100// force the new value into domain. This costs a domain crossing.101collapse(dv, dv->getFirstDomain());102assert(LiveRegs[rx] && "Not live after collapse?");103LiveRegs[rx]->addDomain(domain);104}105} else {106// Set up basic collapsed DomainValue.107setLiveReg(rx, alloc(domain));108}109}110111void ExecutionDomainFix::collapse(DomainValue *dv, unsigned domain) {112assert(dv->hasDomain(domain) && "Cannot collapse");113114// Collapse all the instructions.115while (!dv->Instrs.empty())116TII->setExecutionDomain(*dv->Instrs.pop_back_val(), domain);117dv->setSingleDomain(domain);118119// If there are multiple users, give them new, unique DomainValues.120if (!LiveRegs.empty() && dv->Refs > 1)121for (unsigned rx = 0; rx != NumRegs; ++rx)122if (LiveRegs[rx] == dv)123setLiveReg(rx, alloc(domain));124}125126bool ExecutionDomainFix::merge(DomainValue *A, DomainValue *B) {127assert(!A->isCollapsed() && "Cannot merge into collapsed");128assert(!B->isCollapsed() && "Cannot merge from collapsed");129if (A == B)130return true;131// Restrict to the domains that A and B have in common.132unsigned common = A->getCommonDomains(B->AvailableDomains);133if (!common)134return false;135A->AvailableDomains = common;136A->Instrs.append(B->Instrs.begin(), B->Instrs.end());137138// Clear the old DomainValue so we won't try to swizzle instructions twice.139B->clear();140// All uses of B are referred to A.141B->Next = retain(A);142143for (unsigned rx = 0; rx != NumRegs; ++rx) {144assert(!LiveRegs.empty() && "no space allocated for live registers");145if (LiveRegs[rx] == B)146setLiveReg(rx, A);147}148return true;149}150151void ExecutionDomainFix::enterBasicBlock(152const LoopTraversal::TraversedMBBInfo &TraversedMBB) {153154MachineBasicBlock *MBB = TraversedMBB.MBB;155156// Set up LiveRegs to represent registers entering MBB.157// Set default domain values to 'no domain' (nullptr)158if (LiveRegs.empty())159LiveRegs.assign(NumRegs, nullptr);160161// This is the entry block.162if (MBB->pred_empty()) {163LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << ": entry\n");164return;165}166167// Try to coalesce live-out registers from predecessors.168for (MachineBasicBlock *pred : MBB->predecessors()) {169assert(unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&170"Should have pre-allocated MBBInfos for all MBBs");171LiveRegsDVInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];172// Incoming is null if this is a backedge from a BB173// we haven't processed yet174if (Incoming.empty())175continue;176177for (unsigned rx = 0; rx != NumRegs; ++rx) {178DomainValue *pdv = resolve(Incoming[rx]);179if (!pdv)180continue;181if (!LiveRegs[rx]) {182setLiveReg(rx, pdv);183continue;184}185186// We have a live DomainValue from more than one predecessor.187if (LiveRegs[rx]->isCollapsed()) {188// We are already collapsed, but predecessor is not. Force it.189unsigned Domain = LiveRegs[rx]->getFirstDomain();190if (!pdv->isCollapsed() && pdv->hasDomain(Domain))191collapse(pdv, Domain);192continue;193}194195// Currently open, merge in predecessor.196if (!pdv->isCollapsed())197merge(LiveRegs[rx], pdv);198else199force(rx, pdv->getFirstDomain());200}201}202LLVM_DEBUG(dbgs() << printMBBReference(*MBB)203<< (!TraversedMBB.IsDone ? ": incomplete\n"204: ": all preds known\n"));205}206207void ExecutionDomainFix::leaveBasicBlock(208const LoopTraversal::TraversedMBBInfo &TraversedMBB) {209assert(!LiveRegs.empty() && "Must enter basic block first.");210unsigned MBBNumber = TraversedMBB.MBB->getNumber();211assert(MBBNumber < MBBOutRegsInfos.size() &&212"Unexpected basic block number.");213// Save register clearances at end of MBB - used by enterBasicBlock().214for (DomainValue *OldLiveReg : MBBOutRegsInfos[MBBNumber]) {215release(OldLiveReg);216}217MBBOutRegsInfos[MBBNumber] = LiveRegs;218LiveRegs.clear();219}220221bool ExecutionDomainFix::visitInstr(MachineInstr *MI) {222// Update instructions with explicit execution domains.223std::pair<uint16_t, uint16_t> DomP = TII->getExecutionDomain(*MI);224if (DomP.first) {225if (DomP.second)226visitSoftInstr(MI, DomP.second);227else228visitHardInstr(MI, DomP.first);229}230231return !DomP.first;232}233234void ExecutionDomainFix::processDefs(MachineInstr *MI, bool Kill) {235assert(!MI->isDebugInstr() && "Won't process debug values");236const MCInstrDesc &MCID = MI->getDesc();237for (unsigned i = 0,238e = MI->isVariadic() ? MI->getNumOperands() : MCID.getNumDefs();239i != e; ++i) {240MachineOperand &MO = MI->getOperand(i);241if (!MO.isReg())242continue;243if (MO.isUse())244continue;245for (int rx : regIndices(MO.getReg())) {246// This instruction explicitly defines rx.247LLVM_DEBUG(dbgs() << printReg(RC->getRegister(rx), TRI) << ":\t" << *MI);248249// Kill off domains redefined by generic instructions.250if (Kill)251kill(rx);252}253}254}255256void ExecutionDomainFix::visitHardInstr(MachineInstr *mi, unsigned domain) {257// Collapse all uses.258for (unsigned i = mi->getDesc().getNumDefs(),259e = mi->getDesc().getNumOperands();260i != e; ++i) {261MachineOperand &mo = mi->getOperand(i);262if (!mo.isReg())263continue;264for (int rx : regIndices(mo.getReg())) {265force(rx, domain);266}267}268269// Kill all defs and force them.270for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {271MachineOperand &mo = mi->getOperand(i);272if (!mo.isReg())273continue;274for (int rx : regIndices(mo.getReg())) {275kill(rx);276force(rx, domain);277}278}279}280281void ExecutionDomainFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {282// Bitmask of available domains for this instruction after taking collapsed283// operands into account.284unsigned available = mask;285286// Scan the explicit use operands for incoming domains.287SmallVector<int, 4> used;288if (!LiveRegs.empty())289for (unsigned i = mi->getDesc().getNumDefs(),290e = mi->getDesc().getNumOperands();291i != e; ++i) {292MachineOperand &mo = mi->getOperand(i);293if (!mo.isReg())294continue;295for (int rx : regIndices(mo.getReg())) {296DomainValue *dv = LiveRegs[rx];297if (dv == nullptr)298continue;299// Bitmask of domains that dv and available have in common.300unsigned common = dv->getCommonDomains(available);301// Is it possible to use this collapsed register for free?302if (dv->isCollapsed()) {303// Restrict available domains to the ones in common with the operand.304// If there are no common domains, we must pay the cross-domain305// penalty for this operand.306if (common)307available = common;308} else if (common)309// Open DomainValue is compatible, save it for merging.310used.push_back(rx);311else312// Open DomainValue is not compatible with instruction. It is useless313// now.314kill(rx);315}316}317318// If the collapsed operands force a single domain, propagate the collapse.319if (isPowerOf2_32(available)) {320unsigned domain = llvm::countr_zero(available);321TII->setExecutionDomain(*mi, domain);322visitHardInstr(mi, domain);323return;324}325326// Kill off any remaining uses that don't match available, and build a list of327// incoming DomainValues that we want to merge.328SmallVector<int, 4> Regs;329for (int rx : used) {330assert(!LiveRegs.empty() && "no space allocated for live registers");331DomainValue *&LR = LiveRegs[rx];332// This useless DomainValue could have been missed above.333if (!LR->getCommonDomains(available)) {334kill(rx);335continue;336}337// Sorted insertion.338// Enables giving priority to the latest domains during merging.339const int Def = RDA->getReachingDef(mi, RC->getRegister(rx));340auto I = partition_point(Regs, [&](int I) {341return RDA->getReachingDef(mi, RC->getRegister(I)) <= Def;342});343Regs.insert(I, rx);344}345346// doms are now sorted in order of appearance. Try to merge them all, giving347// priority to the latest ones.348DomainValue *dv = nullptr;349while (!Regs.empty()) {350if (!dv) {351dv = LiveRegs[Regs.pop_back_val()];352// Force the first dv to match the current instruction.353dv->AvailableDomains = dv->getCommonDomains(available);354assert(dv->AvailableDomains && "Domain should have been filtered");355continue;356}357358DomainValue *Latest = LiveRegs[Regs.pop_back_val()];359// Skip already merged values.360if (Latest == dv || Latest->Next)361continue;362if (merge(dv, Latest))363continue;364365// If latest didn't merge, it is useless now. Kill all registers using it.366for (int i : used) {367assert(!LiveRegs.empty() && "no space allocated for live registers");368if (LiveRegs[i] == Latest)369kill(i);370}371}372373// dv is the DomainValue we are going to use for this instruction.374if (!dv) {375dv = alloc();376dv->AvailableDomains = available;377}378dv->Instrs.push_back(mi);379380// Finally set all defs and non-collapsed uses to dv. We must iterate through381// all the operators, including imp-def ones.382for (const MachineOperand &mo : mi->operands()) {383if (!mo.isReg())384continue;385for (int rx : regIndices(mo.getReg())) {386if (!LiveRegs[rx] || (mo.isDef() && LiveRegs[rx] != dv)) {387kill(rx);388setLiveReg(rx, dv);389}390}391}392}393394void ExecutionDomainFix::processBasicBlock(395const LoopTraversal::TraversedMBBInfo &TraversedMBB) {396enterBasicBlock(TraversedMBB);397// If this block is not done, it makes little sense to make any decisions398// based on clearance information. We need to make a second pass anyway,399// and by then we'll have better information, so we can avoid doing the work400// to try and break dependencies now.401for (MachineInstr &MI : *TraversedMBB.MBB) {402if (!MI.isDebugInstr()) {403bool Kill = false;404if (TraversedMBB.PrimaryPass)405Kill = visitInstr(&MI);406processDefs(&MI, Kill);407}408}409leaveBasicBlock(TraversedMBB);410}411412bool ExecutionDomainFix::runOnMachineFunction(MachineFunction &mf) {413if (skipFunction(mf.getFunction()))414return false;415MF = &mf;416TII = MF->getSubtarget().getInstrInfo();417TRI = MF->getSubtarget().getRegisterInfo();418LiveRegs.clear();419assert(NumRegs == RC->getNumRegs() && "Bad regclass");420421LLVM_DEBUG(dbgs() << "********** FIX EXECUTION DOMAIN: "422<< TRI->getRegClassName(RC) << " **********\n");423424// If no relevant registers are used in the function, we can skip it425// completely.426bool anyregs = false;427const MachineRegisterInfo &MRI = mf.getRegInfo();428for (unsigned Reg : *RC) {429if (MRI.isPhysRegUsed(Reg)) {430anyregs = true;431break;432}433}434if (!anyregs)435return false;436437RDA = &getAnalysis<ReachingDefAnalysis>();438439// Initialize the AliasMap on the first use.440if (AliasMap.empty()) {441// Given a PhysReg, AliasMap[PhysReg] returns a list of indices into RC and442// therefore the LiveRegs array.443AliasMap.resize(TRI->getNumRegs());444for (unsigned i = 0, e = RC->getNumRegs(); i != e; ++i)445for (MCRegAliasIterator AI(RC->getRegister(i), TRI, true); AI.isValid();446++AI)447AliasMap[*AI].push_back(i);448}449450// Initialize the MBBOutRegsInfos451MBBOutRegsInfos.resize(mf.getNumBlockIDs());452453// Traverse the basic blocks.454LoopTraversal Traversal;455LoopTraversal::TraversalOrder TraversedMBBOrder = Traversal.traverse(mf);456for (const LoopTraversal::TraversedMBBInfo &TraversedMBB : TraversedMBBOrder)457processBasicBlock(TraversedMBB);458459for (const LiveRegsDVInfo &OutLiveRegs : MBBOutRegsInfos)460for (DomainValue *OutLiveReg : OutLiveRegs)461if (OutLiveReg)462release(OutLiveReg);463464MBBOutRegsInfos.clear();465Avail.clear();466Allocator.DestroyAll();467468return false;469}470471472