1c26fbbfbSJakob Stoklund Olesen //===-- LiveRegMatrix.cpp - Track register interference -------------------===//
2c26fbbfbSJakob Stoklund Olesen //
3c26fbbfbSJakob Stoklund Olesen //                     The LLVM Compiler Infrastructure
4c26fbbfbSJakob Stoklund Olesen //
5c26fbbfbSJakob Stoklund Olesen // This file is distributed under the University of Illinois Open Source
6c26fbbfbSJakob Stoklund Olesen // License. See LICENSE.TXT for details.
7c26fbbfbSJakob Stoklund Olesen //
8c26fbbfbSJakob Stoklund Olesen //===----------------------------------------------------------------------===//
9c26fbbfbSJakob Stoklund Olesen //
10c26fbbfbSJakob Stoklund Olesen // This file defines the LiveRegMatrix analysis pass.
11c26fbbfbSJakob Stoklund Olesen //
12c26fbbfbSJakob Stoklund Olesen //===----------------------------------------------------------------------===//
13c26fbbfbSJakob Stoklund Olesen 
14ed0881b2SChandler Carruth #include "llvm/CodeGen/LiveRegMatrix.h"
15866908c4SJakob Stoklund Olesen #include "RegisterCoalescer.h"
16c26fbbfbSJakob Stoklund Olesen #include "llvm/ADT/Statistic.h"
17c26fbbfbSJakob Stoklund Olesen #include "llvm/CodeGen/LiveIntervalAnalysis.h"
1826c9d70dSJakob Stoklund Olesen #include "llvm/CodeGen/VirtRegMap.h"
19c26fbbfbSJakob Stoklund Olesen #include "llvm/Support/Debug.h"
20d9903888SChandler Carruth #include "llvm/Support/raw_ostream.h"
21ed0881b2SChandler Carruth #include "llvm/Target/TargetRegisterInfo.h"
229912bb81SMatthias Braun #include "llvm/Target/TargetSubtargetInfo.h"
23c26fbbfbSJakob Stoklund Olesen 
24c26fbbfbSJakob Stoklund Olesen using namespace llvm;
25c26fbbfbSJakob Stoklund Olesen 
261b9dde08SChandler Carruth #define DEBUG_TYPE "regalloc"
271b9dde08SChandler Carruth 
28c26fbbfbSJakob Stoklund Olesen STATISTIC(NumAssigned   , "Number of registers assigned");
29c26fbbfbSJakob Stoklund Olesen STATISTIC(NumUnassigned , "Number of registers unassigned");
30c26fbbfbSJakob Stoklund Olesen 
31c26fbbfbSJakob Stoklund Olesen char LiveRegMatrix::ID = 0;
32c26fbbfbSJakob Stoklund Olesen INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix",
33c26fbbfbSJakob Stoklund Olesen                       "Live Register Matrix", false, false)
34c26fbbfbSJakob Stoklund Olesen INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
35c26fbbfbSJakob Stoklund Olesen INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
36c26fbbfbSJakob Stoklund Olesen INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix",
37c26fbbfbSJakob Stoklund Olesen                     "Live Register Matrix", false, false)
38c26fbbfbSJakob Stoklund Olesen 
39c26fbbfbSJakob Stoklund Olesen LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID),
40c26fbbfbSJakob Stoklund Olesen   UserTag(0), RegMaskTag(0), RegMaskVirtReg(0) {}
41c26fbbfbSJakob Stoklund Olesen 
42c26fbbfbSJakob Stoklund Olesen void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const {
43c26fbbfbSJakob Stoklund Olesen   AU.setPreservesAll();
44c26fbbfbSJakob Stoklund Olesen   AU.addRequiredTransitive<LiveIntervals>();
45c26fbbfbSJakob Stoklund Olesen   AU.addRequiredTransitive<VirtRegMap>();
46c26fbbfbSJakob Stoklund Olesen   MachineFunctionPass::getAnalysisUsage(AU);
47c26fbbfbSJakob Stoklund Olesen }
48c26fbbfbSJakob Stoklund Olesen 
49c26fbbfbSJakob Stoklund Olesen bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) {
50fc6de428SEric Christopher   TRI = MF.getSubtarget().getRegisterInfo();
51c26fbbfbSJakob Stoklund Olesen   LIS = &getAnalysis<LiveIntervals>();
52c26fbbfbSJakob Stoklund Olesen   VRM = &getAnalysis<VirtRegMap>();
53c26fbbfbSJakob Stoklund Olesen 
54c26fbbfbSJakob Stoklund Olesen   unsigned NumRegUnits = TRI->getNumRegUnits();
55c26fbbfbSJakob Stoklund Olesen   if (NumRegUnits != Matrix.size())
56c26fbbfbSJakob Stoklund Olesen     Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]);
57c26fbbfbSJakob Stoklund Olesen   Matrix.init(LIUAlloc, NumRegUnits);
58c26fbbfbSJakob Stoklund Olesen 
59c26fbbfbSJakob Stoklund Olesen   // Make sure no stale queries get reused.
60c26fbbfbSJakob Stoklund Olesen   invalidateVirtRegs();
61c26fbbfbSJakob Stoklund Olesen   return false;
62c26fbbfbSJakob Stoklund Olesen }
63c26fbbfbSJakob Stoklund Olesen 
64c26fbbfbSJakob Stoklund Olesen void LiveRegMatrix::releaseMemory() {
65c26fbbfbSJakob Stoklund Olesen   for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
66c26fbbfbSJakob Stoklund Olesen     Matrix[i].clear();
6712ae04bdSPuyan Lotfi     // No need to clear Queries here, since LiveIntervalUnion::Query doesn't
6812ae04bdSPuyan Lotfi     // have anything important to clear and LiveRegMatrix's runOnFunction()
6956440fd8SAhmed Charles     // does a std::unique_ptr::reset anyways.
70c26fbbfbSJakob Stoklund Olesen   }
71c26fbbfbSJakob Stoklund Olesen }
72c26fbbfbSJakob Stoklund Olesen 
73587e2741SMatthias Braun template <typename Callable>
74b7d3311cSBenjamin Kramer static bool foreachUnit(const TargetRegisterInfo *TRI,
75b7d3311cSBenjamin Kramer                         LiveInterval &VRegInterval, unsigned PhysReg,
76b7d3311cSBenjamin Kramer                         Callable Func) {
77587e2741SMatthias Braun   if (VRegInterval.hasSubRanges()) {
78587e2741SMatthias Braun     for (MCRegUnitMaskIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
79587e2741SMatthias Braun       unsigned Unit = (*Units).first;
80e6a2485eSMatthias Braun       LaneBitmask Mask = (*Units).second;
8109afa1eaSMatthias Braun       for (LiveInterval::SubRange &S : VRegInterval.subranges()) {
82*ea9f8ce0SKrzysztof Parzyszek         if ((S.LaneMask & Mask).any()) {
8309afa1eaSMatthias Braun           if (Func(Unit, S))
84587e2741SMatthias Braun             return true;
85587e2741SMatthias Braun           break;
86587e2741SMatthias Braun         }
87587e2741SMatthias Braun       }
88587e2741SMatthias Braun     }
89587e2741SMatthias Braun   } else {
90587e2741SMatthias Braun     for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
91587e2741SMatthias Braun       if (Func(*Units, VRegInterval))
92587e2741SMatthias Braun         return true;
93587e2741SMatthias Braun     }
94587e2741SMatthias Braun   }
95587e2741SMatthias Braun   return false;
96587e2741SMatthias Braun }
97587e2741SMatthias Braun 
98c26fbbfbSJakob Stoklund Olesen void LiveRegMatrix::assign(LiveInterval &VirtReg, unsigned PhysReg) {
99c26fbbfbSJakob Stoklund Olesen   DEBUG(dbgs() << "assigning " << PrintReg(VirtReg.reg, TRI)
100c26fbbfbSJakob Stoklund Olesen                << " to " << PrintReg(PhysReg, TRI) << ':');
101c26fbbfbSJakob Stoklund Olesen   assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment");
102c26fbbfbSJakob Stoklund Olesen   VRM->assignVirt2Phys(VirtReg.reg, PhysReg);
103587e2741SMatthias Braun 
104587e2741SMatthias Braun   foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
105587e2741SMatthias Braun                                          const LiveRange &Range) {
106587e2741SMatthias Braun     DEBUG(dbgs() << ' ' << PrintRegUnit(Unit, TRI) << ' ' << Range);
107587e2741SMatthias Braun     Matrix[Unit].unify(VirtReg, Range);
108587e2741SMatthias Braun     return false;
109587e2741SMatthias Braun   });
110587e2741SMatthias Braun 
111c26fbbfbSJakob Stoklund Olesen   ++NumAssigned;
112c26fbbfbSJakob Stoklund Olesen   DEBUG(dbgs() << '\n');
113c26fbbfbSJakob Stoklund Olesen }
114c26fbbfbSJakob Stoklund Olesen 
115c26fbbfbSJakob Stoklund Olesen void LiveRegMatrix::unassign(LiveInterval &VirtReg) {
116c26fbbfbSJakob Stoklund Olesen   unsigned PhysReg = VRM->getPhys(VirtReg.reg);
117c26fbbfbSJakob Stoklund Olesen   DEBUG(dbgs() << "unassigning " << PrintReg(VirtReg.reg, TRI)
118c26fbbfbSJakob Stoklund Olesen                << " from " << PrintReg(PhysReg, TRI) << ':');
119c26fbbfbSJakob Stoklund Olesen   VRM->clearVirt(VirtReg.reg);
120587e2741SMatthias Braun 
121587e2741SMatthias Braun   foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
122587e2741SMatthias Braun                                          const LiveRange &Range) {
123587e2741SMatthias Braun     DEBUG(dbgs() << ' ' << PrintRegUnit(Unit, TRI));
124587e2741SMatthias Braun     Matrix[Unit].extract(VirtReg, Range);
125587e2741SMatthias Braun     return false;
126587e2741SMatthias Braun   });
127587e2741SMatthias Braun 
128c26fbbfbSJakob Stoklund Olesen   ++NumUnassigned;
129c26fbbfbSJakob Stoklund Olesen   DEBUG(dbgs() << '\n');
130c26fbbfbSJakob Stoklund Olesen }
131c26fbbfbSJakob Stoklund Olesen 
132953393a7SMatthias Braun bool LiveRegMatrix::isPhysRegUsed(unsigned PhysReg) const {
133953393a7SMatthias Braun   for (MCRegUnitIterator Unit(PhysReg, TRI); Unit.isValid(); ++Unit) {
134953393a7SMatthias Braun     if (!Matrix[*Unit].empty())
135953393a7SMatthias Braun       return true;
136953393a7SMatthias Braun   }
137953393a7SMatthias Braun   return false;
138953393a7SMatthias Braun }
139953393a7SMatthias Braun 
140c26fbbfbSJakob Stoklund Olesen bool LiveRegMatrix::checkRegMaskInterference(LiveInterval &VirtReg,
141c26fbbfbSJakob Stoklund Olesen                                              unsigned PhysReg) {
142c26fbbfbSJakob Stoklund Olesen   // Check if the cached information is valid.
143c26fbbfbSJakob Stoklund Olesen   // The same BitVector can be reused for all PhysRegs.
144c26fbbfbSJakob Stoklund Olesen   // We could cache multiple VirtRegs if it becomes necessary.
145c26fbbfbSJakob Stoklund Olesen   if (RegMaskVirtReg != VirtReg.reg || RegMaskTag != UserTag) {
146c26fbbfbSJakob Stoklund Olesen     RegMaskVirtReg = VirtReg.reg;
147c26fbbfbSJakob Stoklund Olesen     RegMaskTag = UserTag;
148c26fbbfbSJakob Stoklund Olesen     RegMaskUsable.clear();
149c26fbbfbSJakob Stoklund Olesen     LIS->checkRegMaskInterference(VirtReg, RegMaskUsable);
150c26fbbfbSJakob Stoklund Olesen   }
151c26fbbfbSJakob Stoklund Olesen 
152c26fbbfbSJakob Stoklund Olesen   // The BitVector is indexed by PhysReg, not register unit.
153c26fbbfbSJakob Stoklund Olesen   // Regmask interference is more fine grained than regunits.
154c26fbbfbSJakob Stoklund Olesen   // For example, a Win64 call can clobber %ymm8 yet preserve %xmm8.
15513dffcb7SJakob Stoklund Olesen   return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg));
156c26fbbfbSJakob Stoklund Olesen }
157c26fbbfbSJakob Stoklund Olesen 
158c26fbbfbSJakob Stoklund Olesen bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg,
159c26fbbfbSJakob Stoklund Olesen                                              unsigned PhysReg) {
160c26fbbfbSJakob Stoklund Olesen   if (VirtReg.empty())
161c26fbbfbSJakob Stoklund Olesen     return false;
162866908c4SJakob Stoklund Olesen   CoalescerPair CP(VirtReg.reg, PhysReg, *TRI);
163587e2741SMatthias Braun 
164587e2741SMatthias Braun   bool Result = foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
165587e2741SMatthias Braun                                                        const LiveRange &Range) {
166587e2741SMatthias Braun     const LiveRange &UnitRange = LIS->getRegUnit(Unit);
167587e2741SMatthias Braun     return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
168587e2741SMatthias Braun   });
169587e2741SMatthias Braun   return Result;
170c26fbbfbSJakob Stoklund Olesen }
171c26fbbfbSJakob Stoklund Olesen 
172c26fbbfbSJakob Stoklund Olesen LiveIntervalUnion::Query &LiveRegMatrix::query(LiveInterval &VirtReg,
173c26fbbfbSJakob Stoklund Olesen                                                unsigned RegUnit) {
174c26fbbfbSJakob Stoklund Olesen   LiveIntervalUnion::Query &Q = Queries[RegUnit];
175c26fbbfbSJakob Stoklund Olesen   Q.init(UserTag, &VirtReg, &Matrix[RegUnit]);
176c26fbbfbSJakob Stoklund Olesen   return Q;
177c26fbbfbSJakob Stoklund Olesen }
178c26fbbfbSJakob Stoklund Olesen 
179c26fbbfbSJakob Stoklund Olesen LiveRegMatrix::InterferenceKind
180c26fbbfbSJakob Stoklund Olesen LiveRegMatrix::checkInterference(LiveInterval &VirtReg, unsigned PhysReg) {
181c26fbbfbSJakob Stoklund Olesen   if (VirtReg.empty())
182c26fbbfbSJakob Stoklund Olesen     return IK_Free;
183c26fbbfbSJakob Stoklund Olesen 
184c26fbbfbSJakob Stoklund Olesen   // Regmask interference is the fastest check.
185c26fbbfbSJakob Stoklund Olesen   if (checkRegMaskInterference(VirtReg, PhysReg))
186c26fbbfbSJakob Stoklund Olesen     return IK_RegMask;
187c26fbbfbSJakob Stoklund Olesen 
188c26fbbfbSJakob Stoklund Olesen   // Check for fixed interference.
189c26fbbfbSJakob Stoklund Olesen   if (checkRegUnitInterference(VirtReg, PhysReg))
190c26fbbfbSJakob Stoklund Olesen     return IK_RegUnit;
191c26fbbfbSJakob Stoklund Olesen 
192c26fbbfbSJakob Stoklund Olesen   // Check the matrix for virtual register interference.
193c26fbbfbSJakob Stoklund Olesen   for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units)
194c26fbbfbSJakob Stoklund Olesen     if (query(VirtReg, *Units).checkInterference())
195c26fbbfbSJakob Stoklund Olesen       return IK_VirtReg;
196c26fbbfbSJakob Stoklund Olesen 
197c26fbbfbSJakob Stoklund Olesen   return IK_Free;
198c26fbbfbSJakob Stoklund Olesen }
199