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