xref: /src/contrib/llvm-project/llvm/lib/CodeGen/ExecutionDomainFix.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1eb11fae6SDimitry Andric //===- ExecutionDomainFix.cpp - Fix execution domain issues ----*- C++ -*--===//
2eb11fae6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eb11fae6SDimitry Andric //
7eb11fae6SDimitry Andric //===----------------------------------------------------------------------===//
8eb11fae6SDimitry Andric 
9eb11fae6SDimitry Andric #include "llvm/CodeGen/ExecutionDomainFix.h"
10eb11fae6SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
11eb11fae6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
121d5ae102SDimitry Andric #include "llvm/Support/Debug.h"
13eb11fae6SDimitry Andric 
14eb11fae6SDimitry Andric using namespace llvm;
15eb11fae6SDimitry Andric 
16eb11fae6SDimitry Andric #define DEBUG_TYPE "execution-deps-fix"
17eb11fae6SDimitry Andric 
18eb11fae6SDimitry Andric iterator_range<SmallVectorImpl<int>::const_iterator>
regIndices(unsigned Reg) const19eb11fae6SDimitry Andric ExecutionDomainFix::regIndices(unsigned Reg) const {
20eb11fae6SDimitry Andric   assert(Reg < AliasMap.size() && "Invalid register");
21eb11fae6SDimitry Andric   const auto &Entry = AliasMap[Reg];
22eb11fae6SDimitry Andric   return make_range(Entry.begin(), Entry.end());
23eb11fae6SDimitry Andric }
24eb11fae6SDimitry Andric 
alloc(int domain)25eb11fae6SDimitry Andric DomainValue *ExecutionDomainFix::alloc(int domain) {
26eb11fae6SDimitry Andric   DomainValue *dv = Avail.empty() ? new (Allocator.Allocate()) DomainValue
27eb11fae6SDimitry Andric                                   : Avail.pop_back_val();
28eb11fae6SDimitry Andric   if (domain >= 0)
29eb11fae6SDimitry Andric     dv->addDomain(domain);
30eb11fae6SDimitry Andric   assert(dv->Refs == 0 && "Reference count wasn't cleared");
31eb11fae6SDimitry Andric   assert(!dv->Next && "Chained DomainValue shouldn't have been recycled");
32eb11fae6SDimitry Andric   return dv;
33eb11fae6SDimitry Andric }
34eb11fae6SDimitry Andric 
release(DomainValue * DV)35eb11fae6SDimitry Andric void ExecutionDomainFix::release(DomainValue *DV) {
36eb11fae6SDimitry Andric   while (DV) {
37eb11fae6SDimitry Andric     assert(DV->Refs && "Bad DomainValue");
38eb11fae6SDimitry Andric     if (--DV->Refs)
39eb11fae6SDimitry Andric       return;
40eb11fae6SDimitry Andric 
41eb11fae6SDimitry Andric     // There are no more DV references. Collapse any contained instructions.
42eb11fae6SDimitry Andric     if (DV->AvailableDomains && !DV->isCollapsed())
43eb11fae6SDimitry Andric       collapse(DV, DV->getFirstDomain());
44eb11fae6SDimitry Andric 
45eb11fae6SDimitry Andric     DomainValue *Next = DV->Next;
46eb11fae6SDimitry Andric     DV->clear();
47eb11fae6SDimitry Andric     Avail.push_back(DV);
48eb11fae6SDimitry Andric     // Also release the next DomainValue in the chain.
49eb11fae6SDimitry Andric     DV = Next;
50eb11fae6SDimitry Andric   }
51eb11fae6SDimitry Andric }
52eb11fae6SDimitry Andric 
resolve(DomainValue * & DVRef)53eb11fae6SDimitry Andric DomainValue *ExecutionDomainFix::resolve(DomainValue *&DVRef) {
54eb11fae6SDimitry Andric   DomainValue *DV = DVRef;
55eb11fae6SDimitry Andric   if (!DV || !DV->Next)
56eb11fae6SDimitry Andric     return DV;
57eb11fae6SDimitry Andric 
58eb11fae6SDimitry Andric   // DV has a chain. Find the end.
59eb11fae6SDimitry Andric   do
60eb11fae6SDimitry Andric     DV = DV->Next;
61eb11fae6SDimitry Andric   while (DV->Next);
62eb11fae6SDimitry Andric 
63eb11fae6SDimitry Andric   // Update DVRef to point to DV.
64eb11fae6SDimitry Andric   retain(DV);
65eb11fae6SDimitry Andric   release(DVRef);
66eb11fae6SDimitry Andric   DVRef = DV;
67eb11fae6SDimitry Andric   return DV;
68eb11fae6SDimitry Andric }
69eb11fae6SDimitry Andric 
setLiveReg(int rx,DomainValue * dv)70eb11fae6SDimitry Andric void ExecutionDomainFix::setLiveReg(int rx, DomainValue *dv) {
71eb11fae6SDimitry Andric   assert(unsigned(rx) < NumRegs && "Invalid index");
72eb11fae6SDimitry Andric   assert(!LiveRegs.empty() && "Must enter basic block first.");
73eb11fae6SDimitry Andric 
74eb11fae6SDimitry Andric   if (LiveRegs[rx] == dv)
75eb11fae6SDimitry Andric     return;
76eb11fae6SDimitry Andric   if (LiveRegs[rx])
77eb11fae6SDimitry Andric     release(LiveRegs[rx]);
78eb11fae6SDimitry Andric   LiveRegs[rx] = retain(dv);
79eb11fae6SDimitry Andric }
80eb11fae6SDimitry Andric 
kill(int rx)81eb11fae6SDimitry Andric void ExecutionDomainFix::kill(int rx) {
82eb11fae6SDimitry Andric   assert(unsigned(rx) < NumRegs && "Invalid index");
83eb11fae6SDimitry Andric   assert(!LiveRegs.empty() && "Must enter basic block first.");
84eb11fae6SDimitry Andric   if (!LiveRegs[rx])
85eb11fae6SDimitry Andric     return;
86eb11fae6SDimitry Andric 
87eb11fae6SDimitry Andric   release(LiveRegs[rx]);
88eb11fae6SDimitry Andric   LiveRegs[rx] = nullptr;
89eb11fae6SDimitry Andric }
90eb11fae6SDimitry Andric 
force(int rx,unsigned domain)91eb11fae6SDimitry Andric void ExecutionDomainFix::force(int rx, unsigned domain) {
92eb11fae6SDimitry Andric   assert(unsigned(rx) < NumRegs && "Invalid index");
93eb11fae6SDimitry Andric   assert(!LiveRegs.empty() && "Must enter basic block first.");
94eb11fae6SDimitry Andric   if (DomainValue *dv = LiveRegs[rx]) {
95eb11fae6SDimitry Andric     if (dv->isCollapsed())
96eb11fae6SDimitry Andric       dv->addDomain(domain);
97eb11fae6SDimitry Andric     else if (dv->hasDomain(domain))
98eb11fae6SDimitry Andric       collapse(dv, domain);
99eb11fae6SDimitry Andric     else {
100eb11fae6SDimitry Andric       // This is an incompatible open DomainValue. Collapse it to whatever and
101eb11fae6SDimitry Andric       // force the new value into domain. This costs a domain crossing.
102eb11fae6SDimitry Andric       collapse(dv, dv->getFirstDomain());
103eb11fae6SDimitry Andric       assert(LiveRegs[rx] && "Not live after collapse?");
104eb11fae6SDimitry Andric       LiveRegs[rx]->addDomain(domain);
105eb11fae6SDimitry Andric     }
106eb11fae6SDimitry Andric   } else {
107eb11fae6SDimitry Andric     // Set up basic collapsed DomainValue.
108eb11fae6SDimitry Andric     setLiveReg(rx, alloc(domain));
109eb11fae6SDimitry Andric   }
110eb11fae6SDimitry Andric }
111eb11fae6SDimitry Andric 
collapse(DomainValue * dv,unsigned domain)112eb11fae6SDimitry Andric void ExecutionDomainFix::collapse(DomainValue *dv, unsigned domain) {
113eb11fae6SDimitry Andric   assert(dv->hasDomain(domain) && "Cannot collapse");
114eb11fae6SDimitry Andric 
115eb11fae6SDimitry Andric   // Collapse all the instructions.
116eb11fae6SDimitry Andric   while (!dv->Instrs.empty())
117eb11fae6SDimitry Andric     TII->setExecutionDomain(*dv->Instrs.pop_back_val(), domain);
118eb11fae6SDimitry Andric   dv->setSingleDomain(domain);
119eb11fae6SDimitry Andric 
120eb11fae6SDimitry Andric   // If there are multiple users, give them new, unique DomainValues.
121eb11fae6SDimitry Andric   if (!LiveRegs.empty() && dv->Refs > 1)
122eb11fae6SDimitry Andric     for (unsigned rx = 0; rx != NumRegs; ++rx)
123eb11fae6SDimitry Andric       if (LiveRegs[rx] == dv)
124eb11fae6SDimitry Andric         setLiveReg(rx, alloc(domain));
125eb11fae6SDimitry Andric }
126eb11fae6SDimitry Andric 
merge(DomainValue * A,DomainValue * B)127eb11fae6SDimitry Andric bool ExecutionDomainFix::merge(DomainValue *A, DomainValue *B) {
128eb11fae6SDimitry Andric   assert(!A->isCollapsed() && "Cannot merge into collapsed");
129eb11fae6SDimitry Andric   assert(!B->isCollapsed() && "Cannot merge from collapsed");
130eb11fae6SDimitry Andric   if (A == B)
131eb11fae6SDimitry Andric     return true;
132eb11fae6SDimitry Andric   // Restrict to the domains that A and B have in common.
133eb11fae6SDimitry Andric   unsigned common = A->getCommonDomains(B->AvailableDomains);
134eb11fae6SDimitry Andric   if (!common)
135eb11fae6SDimitry Andric     return false;
136eb11fae6SDimitry Andric   A->AvailableDomains = common;
137eb11fae6SDimitry Andric   A->Instrs.append(B->Instrs.begin(), B->Instrs.end());
138eb11fae6SDimitry Andric 
139eb11fae6SDimitry Andric   // Clear the old DomainValue so we won't try to swizzle instructions twice.
140eb11fae6SDimitry Andric   B->clear();
141eb11fae6SDimitry Andric   // All uses of B are referred to A.
142eb11fae6SDimitry Andric   B->Next = retain(A);
143eb11fae6SDimitry Andric 
144eb11fae6SDimitry Andric   for (unsigned rx = 0; rx != NumRegs; ++rx) {
145eb11fae6SDimitry Andric     assert(!LiveRegs.empty() && "no space allocated for live registers");
146eb11fae6SDimitry Andric     if (LiveRegs[rx] == B)
147eb11fae6SDimitry Andric       setLiveReg(rx, A);
148eb11fae6SDimitry Andric   }
149eb11fae6SDimitry Andric   return true;
150eb11fae6SDimitry Andric }
151eb11fae6SDimitry Andric 
enterBasicBlock(const LoopTraversal::TraversedMBBInfo & TraversedMBB)152eb11fae6SDimitry Andric void ExecutionDomainFix::enterBasicBlock(
153eb11fae6SDimitry Andric     const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
154eb11fae6SDimitry Andric 
155eb11fae6SDimitry Andric   MachineBasicBlock *MBB = TraversedMBB.MBB;
156eb11fae6SDimitry Andric 
157eb11fae6SDimitry Andric   // Set up LiveRegs to represent registers entering MBB.
158eb11fae6SDimitry Andric   // Set default domain values to 'no domain' (nullptr)
159eb11fae6SDimitry Andric   if (LiveRegs.empty())
160eb11fae6SDimitry Andric     LiveRegs.assign(NumRegs, nullptr);
161eb11fae6SDimitry Andric 
162eb11fae6SDimitry Andric   // This is the entry block.
163eb11fae6SDimitry Andric   if (MBB->pred_empty()) {
164eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << ": entry\n");
165eb11fae6SDimitry Andric     return;
166eb11fae6SDimitry Andric   }
167eb11fae6SDimitry Andric 
168eb11fae6SDimitry Andric   // Try to coalesce live-out registers from predecessors.
169eb11fae6SDimitry Andric   for (MachineBasicBlock *pred : MBB->predecessors()) {
170eb11fae6SDimitry Andric     assert(unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&
171eb11fae6SDimitry Andric            "Should have pre-allocated MBBInfos for all MBBs");
172eb11fae6SDimitry Andric     LiveRegsDVInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
173eb11fae6SDimitry Andric     // Incoming is null if this is a backedge from a BB
174eb11fae6SDimitry Andric     // we haven't processed yet
175eb11fae6SDimitry Andric     if (Incoming.empty())
176eb11fae6SDimitry Andric       continue;
177eb11fae6SDimitry Andric 
178eb11fae6SDimitry Andric     for (unsigned rx = 0; rx != NumRegs; ++rx) {
179eb11fae6SDimitry Andric       DomainValue *pdv = resolve(Incoming[rx]);
180eb11fae6SDimitry Andric       if (!pdv)
181eb11fae6SDimitry Andric         continue;
182eb11fae6SDimitry Andric       if (!LiveRegs[rx]) {
183eb11fae6SDimitry Andric         setLiveReg(rx, pdv);
184eb11fae6SDimitry Andric         continue;
185eb11fae6SDimitry Andric       }
186eb11fae6SDimitry Andric 
187eb11fae6SDimitry Andric       // We have a live DomainValue from more than one predecessor.
188eb11fae6SDimitry Andric       if (LiveRegs[rx]->isCollapsed()) {
189eb11fae6SDimitry Andric         // We are already collapsed, but predecessor is not. Force it.
190eb11fae6SDimitry Andric         unsigned Domain = LiveRegs[rx]->getFirstDomain();
191eb11fae6SDimitry Andric         if (!pdv->isCollapsed() && pdv->hasDomain(Domain))
192eb11fae6SDimitry Andric           collapse(pdv, Domain);
193eb11fae6SDimitry Andric         continue;
194eb11fae6SDimitry Andric       }
195eb11fae6SDimitry Andric 
196eb11fae6SDimitry Andric       // Currently open, merge in predecessor.
197eb11fae6SDimitry Andric       if (!pdv->isCollapsed())
198eb11fae6SDimitry Andric         merge(LiveRegs[rx], pdv);
199eb11fae6SDimitry Andric       else
200eb11fae6SDimitry Andric         force(rx, pdv->getFirstDomain());
201eb11fae6SDimitry Andric     }
202eb11fae6SDimitry Andric   }
203eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << printMBBReference(*MBB)
204eb11fae6SDimitry Andric                     << (!TraversedMBB.IsDone ? ": incomplete\n"
205eb11fae6SDimitry Andric                                              : ": all preds known\n"));
206eb11fae6SDimitry Andric }
207eb11fae6SDimitry Andric 
leaveBasicBlock(const LoopTraversal::TraversedMBBInfo & TraversedMBB)208eb11fae6SDimitry Andric void ExecutionDomainFix::leaveBasicBlock(
209eb11fae6SDimitry Andric     const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
210eb11fae6SDimitry Andric   assert(!LiveRegs.empty() && "Must enter basic block first.");
211eb11fae6SDimitry Andric   unsigned MBBNumber = TraversedMBB.MBB->getNumber();
212eb11fae6SDimitry Andric   assert(MBBNumber < MBBOutRegsInfos.size() &&
213eb11fae6SDimitry Andric          "Unexpected basic block number.");
214eb11fae6SDimitry Andric   // Save register clearances at end of MBB - used by enterBasicBlock().
215eb11fae6SDimitry Andric   for (DomainValue *OldLiveReg : MBBOutRegsInfos[MBBNumber]) {
216eb11fae6SDimitry Andric     release(OldLiveReg);
217eb11fae6SDimitry Andric   }
218eb11fae6SDimitry Andric   MBBOutRegsInfos[MBBNumber] = LiveRegs;
219eb11fae6SDimitry Andric   LiveRegs.clear();
220eb11fae6SDimitry Andric }
221eb11fae6SDimitry Andric 
visitInstr(MachineInstr * MI)222eb11fae6SDimitry Andric bool ExecutionDomainFix::visitInstr(MachineInstr *MI) {
223eb11fae6SDimitry Andric   // Update instructions with explicit execution domains.
224eb11fae6SDimitry Andric   std::pair<uint16_t, uint16_t> DomP = TII->getExecutionDomain(*MI);
225eb11fae6SDimitry Andric   if (DomP.first) {
226eb11fae6SDimitry Andric     if (DomP.second)
227eb11fae6SDimitry Andric       visitSoftInstr(MI, DomP.second);
228eb11fae6SDimitry Andric     else
229eb11fae6SDimitry Andric       visitHardInstr(MI, DomP.first);
230eb11fae6SDimitry Andric   }
231eb11fae6SDimitry Andric 
232eb11fae6SDimitry Andric   return !DomP.first;
233eb11fae6SDimitry Andric }
234eb11fae6SDimitry Andric 
processDefs(MachineInstr * MI,bool Kill)235eb11fae6SDimitry Andric void ExecutionDomainFix::processDefs(MachineInstr *MI, bool Kill) {
236eb11fae6SDimitry Andric   assert(!MI->isDebugInstr() && "Won't process debug values");
237eb11fae6SDimitry Andric   const MCInstrDesc &MCID = MI->getDesc();
238eb11fae6SDimitry Andric   for (unsigned i = 0,
239eb11fae6SDimitry Andric                 e = MI->isVariadic() ? MI->getNumOperands() : MCID.getNumDefs();
240eb11fae6SDimitry Andric        i != e; ++i) {
241eb11fae6SDimitry Andric     MachineOperand &MO = MI->getOperand(i);
242eb11fae6SDimitry Andric     if (!MO.isReg())
243eb11fae6SDimitry Andric       continue;
244eb11fae6SDimitry Andric     if (MO.isUse())
245eb11fae6SDimitry Andric       continue;
246eb11fae6SDimitry Andric     for (int rx : regIndices(MO.getReg())) {
247eb11fae6SDimitry Andric       // This instruction explicitly defines rx.
248eb11fae6SDimitry Andric       LLVM_DEBUG(dbgs() << printReg(RC->getRegister(rx), TRI) << ":\t" << *MI);
249eb11fae6SDimitry Andric 
250eb11fae6SDimitry Andric       // Kill off domains redefined by generic instructions.
251eb11fae6SDimitry Andric       if (Kill)
252eb11fae6SDimitry Andric         kill(rx);
253eb11fae6SDimitry Andric     }
254eb11fae6SDimitry Andric   }
255eb11fae6SDimitry Andric }
256eb11fae6SDimitry Andric 
visitHardInstr(MachineInstr * mi,unsigned domain)257eb11fae6SDimitry Andric void ExecutionDomainFix::visitHardInstr(MachineInstr *mi, unsigned domain) {
258eb11fae6SDimitry Andric   // Collapse all uses.
259eb11fae6SDimitry Andric   for (unsigned i = mi->getDesc().getNumDefs(),
260eb11fae6SDimitry Andric                 e = mi->getDesc().getNumOperands();
261eb11fae6SDimitry Andric        i != e; ++i) {
262eb11fae6SDimitry Andric     MachineOperand &mo = mi->getOperand(i);
263eb11fae6SDimitry Andric     if (!mo.isReg())
264eb11fae6SDimitry Andric       continue;
265eb11fae6SDimitry Andric     for (int rx : regIndices(mo.getReg())) {
266eb11fae6SDimitry Andric       force(rx, domain);
267eb11fae6SDimitry Andric     }
268eb11fae6SDimitry Andric   }
269eb11fae6SDimitry Andric 
270eb11fae6SDimitry Andric   // Kill all defs and force them.
271eb11fae6SDimitry Andric   for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {
272eb11fae6SDimitry Andric     MachineOperand &mo = mi->getOperand(i);
273eb11fae6SDimitry Andric     if (!mo.isReg())
274eb11fae6SDimitry Andric       continue;
275eb11fae6SDimitry Andric     for (int rx : regIndices(mo.getReg())) {
276eb11fae6SDimitry Andric       kill(rx);
277eb11fae6SDimitry Andric       force(rx, domain);
278eb11fae6SDimitry Andric     }
279eb11fae6SDimitry Andric   }
280eb11fae6SDimitry Andric }
281eb11fae6SDimitry Andric 
visitSoftInstr(MachineInstr * mi,unsigned mask)282eb11fae6SDimitry Andric void ExecutionDomainFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {
283eb11fae6SDimitry Andric   // Bitmask of available domains for this instruction after taking collapsed
284eb11fae6SDimitry Andric   // operands into account.
285eb11fae6SDimitry Andric   unsigned available = mask;
286eb11fae6SDimitry Andric 
287eb11fae6SDimitry Andric   // Scan the explicit use operands for incoming domains.
288eb11fae6SDimitry Andric   SmallVector<int, 4> used;
289eb11fae6SDimitry Andric   if (!LiveRegs.empty())
290eb11fae6SDimitry Andric     for (unsigned i = mi->getDesc().getNumDefs(),
291eb11fae6SDimitry Andric                   e = mi->getDesc().getNumOperands();
292eb11fae6SDimitry Andric          i != e; ++i) {
293eb11fae6SDimitry Andric       MachineOperand &mo = mi->getOperand(i);
294eb11fae6SDimitry Andric       if (!mo.isReg())
295eb11fae6SDimitry Andric         continue;
296eb11fae6SDimitry Andric       for (int rx : regIndices(mo.getReg())) {
297eb11fae6SDimitry Andric         DomainValue *dv = LiveRegs[rx];
298eb11fae6SDimitry Andric         if (dv == nullptr)
299eb11fae6SDimitry Andric           continue;
300eb11fae6SDimitry Andric         // Bitmask of domains that dv and available have in common.
301eb11fae6SDimitry Andric         unsigned common = dv->getCommonDomains(available);
302eb11fae6SDimitry Andric         // Is it possible to use this collapsed register for free?
303eb11fae6SDimitry Andric         if (dv->isCollapsed()) {
304eb11fae6SDimitry Andric           // Restrict available domains to the ones in common with the operand.
305eb11fae6SDimitry Andric           // If there are no common domains, we must pay the cross-domain
306eb11fae6SDimitry Andric           // penalty for this operand.
307eb11fae6SDimitry Andric           if (common)
308eb11fae6SDimitry Andric             available = common;
309eb11fae6SDimitry Andric         } else if (common)
310eb11fae6SDimitry Andric           // Open DomainValue is compatible, save it for merging.
311eb11fae6SDimitry Andric           used.push_back(rx);
312eb11fae6SDimitry Andric         else
313eb11fae6SDimitry Andric           // Open DomainValue is not compatible with instruction. It is useless
314eb11fae6SDimitry Andric           // now.
315eb11fae6SDimitry Andric           kill(rx);
316eb11fae6SDimitry Andric       }
317eb11fae6SDimitry Andric     }
318eb11fae6SDimitry Andric 
319eb11fae6SDimitry Andric   // If the collapsed operands force a single domain, propagate the collapse.
320eb11fae6SDimitry Andric   if (isPowerOf2_32(available)) {
3217fa27ce4SDimitry Andric     unsigned domain = llvm::countr_zero(available);
322eb11fae6SDimitry Andric     TII->setExecutionDomain(*mi, domain);
323eb11fae6SDimitry Andric     visitHardInstr(mi, domain);
324eb11fae6SDimitry Andric     return;
325eb11fae6SDimitry Andric   }
326eb11fae6SDimitry Andric 
327eb11fae6SDimitry Andric   // Kill off any remaining uses that don't match available, and build a list of
328eb11fae6SDimitry Andric   // incoming DomainValues that we want to merge.
329eb11fae6SDimitry Andric   SmallVector<int, 4> Regs;
330eb11fae6SDimitry Andric   for (int rx : used) {
331eb11fae6SDimitry Andric     assert(!LiveRegs.empty() && "no space allocated for live registers");
332eb11fae6SDimitry Andric     DomainValue *&LR = LiveRegs[rx];
333eb11fae6SDimitry Andric     // This useless DomainValue could have been missed above.
334eb11fae6SDimitry Andric     if (!LR->getCommonDomains(available)) {
335eb11fae6SDimitry Andric       kill(rx);
336eb11fae6SDimitry Andric       continue;
337eb11fae6SDimitry Andric     }
338eb11fae6SDimitry Andric     // Sorted insertion.
339eb11fae6SDimitry Andric     // Enables giving priority to the latest domains during merging.
340e6d15924SDimitry Andric     const int Def = RDA->getReachingDef(mi, RC->getRegister(rx));
341e6d15924SDimitry Andric     auto I = partition_point(Regs, [&](int I) {
342e6d15924SDimitry Andric       return RDA->getReachingDef(mi, RC->getRegister(I)) <= Def;
343eb11fae6SDimitry Andric     });
344eb11fae6SDimitry Andric     Regs.insert(I, rx);
345eb11fae6SDimitry Andric   }
346eb11fae6SDimitry Andric 
347eb11fae6SDimitry Andric   // doms are now sorted in order of appearance. Try to merge them all, giving
348eb11fae6SDimitry Andric   // priority to the latest ones.
349eb11fae6SDimitry Andric   DomainValue *dv = nullptr;
350eb11fae6SDimitry Andric   while (!Regs.empty()) {
351eb11fae6SDimitry Andric     if (!dv) {
352eb11fae6SDimitry Andric       dv = LiveRegs[Regs.pop_back_val()];
353eb11fae6SDimitry Andric       // Force the first dv to match the current instruction.
354eb11fae6SDimitry Andric       dv->AvailableDomains = dv->getCommonDomains(available);
355eb11fae6SDimitry Andric       assert(dv->AvailableDomains && "Domain should have been filtered");
356eb11fae6SDimitry Andric       continue;
357eb11fae6SDimitry Andric     }
358eb11fae6SDimitry Andric 
359eb11fae6SDimitry Andric     DomainValue *Latest = LiveRegs[Regs.pop_back_val()];
360eb11fae6SDimitry Andric     // Skip already merged values.
361eb11fae6SDimitry Andric     if (Latest == dv || Latest->Next)
362eb11fae6SDimitry Andric       continue;
363eb11fae6SDimitry Andric     if (merge(dv, Latest))
364eb11fae6SDimitry Andric       continue;
365eb11fae6SDimitry Andric 
366eb11fae6SDimitry Andric     // If latest didn't merge, it is useless now. Kill all registers using it.
367eb11fae6SDimitry Andric     for (int i : used) {
368eb11fae6SDimitry Andric       assert(!LiveRegs.empty() && "no space allocated for live registers");
369eb11fae6SDimitry Andric       if (LiveRegs[i] == Latest)
370eb11fae6SDimitry Andric         kill(i);
371eb11fae6SDimitry Andric     }
372eb11fae6SDimitry Andric   }
373eb11fae6SDimitry Andric 
374eb11fae6SDimitry Andric   // dv is the DomainValue we are going to use for this instruction.
375eb11fae6SDimitry Andric   if (!dv) {
376eb11fae6SDimitry Andric     dv = alloc();
377eb11fae6SDimitry Andric     dv->AvailableDomains = available;
378eb11fae6SDimitry Andric   }
379eb11fae6SDimitry Andric   dv->Instrs.push_back(mi);
380eb11fae6SDimitry Andric 
381eb11fae6SDimitry Andric   // Finally set all defs and non-collapsed uses to dv. We must iterate through
382eb11fae6SDimitry Andric   // all the operators, including imp-def ones.
383344a3780SDimitry Andric   for (const MachineOperand &mo : mi->operands()) {
384eb11fae6SDimitry Andric     if (!mo.isReg())
385eb11fae6SDimitry Andric       continue;
386eb11fae6SDimitry Andric     for (int rx : regIndices(mo.getReg())) {
387eb11fae6SDimitry Andric       if (!LiveRegs[rx] || (mo.isDef() && LiveRegs[rx] != dv)) {
388eb11fae6SDimitry Andric         kill(rx);
389eb11fae6SDimitry Andric         setLiveReg(rx, dv);
390eb11fae6SDimitry Andric       }
391eb11fae6SDimitry Andric     }
392eb11fae6SDimitry Andric   }
393eb11fae6SDimitry Andric }
394eb11fae6SDimitry Andric 
processBasicBlock(const LoopTraversal::TraversedMBBInfo & TraversedMBB)395eb11fae6SDimitry Andric void ExecutionDomainFix::processBasicBlock(
396eb11fae6SDimitry Andric     const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
397eb11fae6SDimitry Andric   enterBasicBlock(TraversedMBB);
398eb11fae6SDimitry Andric   // If this block is not done, it makes little sense to make any decisions
399eb11fae6SDimitry Andric   // based on clearance information. We need to make a second pass anyway,
400eb11fae6SDimitry Andric   // and by then we'll have better information, so we can avoid doing the work
401eb11fae6SDimitry Andric   // to try and break dependencies now.
402eb11fae6SDimitry Andric   for (MachineInstr &MI : *TraversedMBB.MBB) {
403eb11fae6SDimitry Andric     if (!MI.isDebugInstr()) {
404eb11fae6SDimitry Andric       bool Kill = false;
405eb11fae6SDimitry Andric       if (TraversedMBB.PrimaryPass)
406eb11fae6SDimitry Andric         Kill = visitInstr(&MI);
407eb11fae6SDimitry Andric       processDefs(&MI, Kill);
408eb11fae6SDimitry Andric     }
409eb11fae6SDimitry Andric   }
410eb11fae6SDimitry Andric   leaveBasicBlock(TraversedMBB);
411eb11fae6SDimitry Andric }
412eb11fae6SDimitry Andric 
runOnMachineFunction(MachineFunction & mf)413eb11fae6SDimitry Andric bool ExecutionDomainFix::runOnMachineFunction(MachineFunction &mf) {
414eb11fae6SDimitry Andric   if (skipFunction(mf.getFunction()))
415eb11fae6SDimitry Andric     return false;
416eb11fae6SDimitry Andric   MF = &mf;
417eb11fae6SDimitry Andric   TII = MF->getSubtarget().getInstrInfo();
418eb11fae6SDimitry Andric   TRI = MF->getSubtarget().getRegisterInfo();
419eb11fae6SDimitry Andric   LiveRegs.clear();
420eb11fae6SDimitry Andric   assert(NumRegs == RC->getNumRegs() && "Bad regclass");
421eb11fae6SDimitry Andric 
422eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "********** FIX EXECUTION DOMAIN: "
423eb11fae6SDimitry Andric                     << TRI->getRegClassName(RC) << " **********\n");
424eb11fae6SDimitry Andric 
425eb11fae6SDimitry Andric   // If no relevant registers are used in the function, we can skip it
426eb11fae6SDimitry Andric   // completely.
427eb11fae6SDimitry Andric   bool anyregs = false;
428eb11fae6SDimitry Andric   const MachineRegisterInfo &MRI = mf.getRegInfo();
429eb11fae6SDimitry Andric   for (unsigned Reg : *RC) {
430eb11fae6SDimitry Andric     if (MRI.isPhysRegUsed(Reg)) {
431eb11fae6SDimitry Andric       anyregs = true;
432eb11fae6SDimitry Andric       break;
433eb11fae6SDimitry Andric     }
434eb11fae6SDimitry Andric   }
435eb11fae6SDimitry Andric   if (!anyregs)
436eb11fae6SDimitry Andric     return false;
437eb11fae6SDimitry Andric 
438eb11fae6SDimitry Andric   RDA = &getAnalysis<ReachingDefAnalysis>();
439eb11fae6SDimitry Andric 
440eb11fae6SDimitry Andric   // Initialize the AliasMap on the first use.
441eb11fae6SDimitry Andric   if (AliasMap.empty()) {
442eb11fae6SDimitry Andric     // Given a PhysReg, AliasMap[PhysReg] returns a list of indices into RC and
443eb11fae6SDimitry Andric     // therefore the LiveRegs array.
444eb11fae6SDimitry Andric     AliasMap.resize(TRI->getNumRegs());
445eb11fae6SDimitry Andric     for (unsigned i = 0, e = RC->getNumRegs(); i != e; ++i)
446eb11fae6SDimitry Andric       for (MCRegAliasIterator AI(RC->getRegister(i), TRI, true); AI.isValid();
447eb11fae6SDimitry Andric            ++AI)
448eb11fae6SDimitry Andric         AliasMap[*AI].push_back(i);
449eb11fae6SDimitry Andric   }
450eb11fae6SDimitry Andric 
451eb11fae6SDimitry Andric   // Initialize the MBBOutRegsInfos
452eb11fae6SDimitry Andric   MBBOutRegsInfos.resize(mf.getNumBlockIDs());
453eb11fae6SDimitry Andric 
454eb11fae6SDimitry Andric   // Traverse the basic blocks.
455eb11fae6SDimitry Andric   LoopTraversal Traversal;
456eb11fae6SDimitry Andric   LoopTraversal::TraversalOrder TraversedMBBOrder = Traversal.traverse(mf);
457344a3780SDimitry Andric   for (const LoopTraversal::TraversedMBBInfo &TraversedMBB : TraversedMBBOrder)
458eb11fae6SDimitry Andric     processBasicBlock(TraversedMBB);
459eb11fae6SDimitry Andric 
460344a3780SDimitry Andric   for (const LiveRegsDVInfo &OutLiveRegs : MBBOutRegsInfos)
461344a3780SDimitry Andric     for (DomainValue *OutLiveReg : OutLiveRegs)
462eb11fae6SDimitry Andric       if (OutLiveReg)
463eb11fae6SDimitry Andric         release(OutLiveReg);
464344a3780SDimitry Andric 
465eb11fae6SDimitry Andric   MBBOutRegsInfos.clear();
466eb11fae6SDimitry Andric   Avail.clear();
467eb11fae6SDimitry Andric   Allocator.DestroyAll();
468eb11fae6SDimitry Andric 
469eb11fae6SDimitry Andric   return false;
470eb11fae6SDimitry Andric }
471