LLVM API Documentation
00001 //===-- SpillPlacement.cpp - Optimal Spill Code Placement -----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the spill code placement analysis. 00011 // 00012 // Each edge bundle corresponds to a node in a Hopfield network. Constraints on 00013 // basic blocks are weighted by the block frequency and added to become the node 00014 // bias. 00015 // 00016 // Transparent basic blocks have the variable live through, but don't care if it 00017 // is spilled or in a register. These blocks become connections in the Hopfield 00018 // network, again weighted by block frequency. 00019 // 00020 // The Hopfield network minimizes (possibly locally) its energy function: 00021 // 00022 // E = -sum_n V_n * ( B_n + sum_{n, m linked by b} V_m * F_b ) 00023 // 00024 // The energy function represents the expected spill code execution frequency, 00025 // or the cost of spilling. This is a Lyapunov function which never increases 00026 // when a node is updated. It is guaranteed to converge to a local minimum. 00027 // 00028 //===----------------------------------------------------------------------===// 00029 00030 #include "SpillPlacement.h" 00031 #include "llvm/ADT/BitVector.h" 00032 #include "llvm/CodeGen/EdgeBundles.h" 00033 #include "llvm/CodeGen/MachineBasicBlock.h" 00034 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 00035 #include "llvm/CodeGen/MachineFunction.h" 00036 #include "llvm/CodeGen/MachineLoopInfo.h" 00037 #include "llvm/CodeGen/Passes.h" 00038 #include "llvm/Support/Debug.h" 00039 #include "llvm/Support/Format.h" 00040 00041 using namespace llvm; 00042 00043 #define DEBUG_TYPE "spillplacement" 00044 00045 char SpillPlacement::ID = 0; 00046 INITIALIZE_PASS_BEGIN(SpillPlacement, "spill-code-placement", 00047 "Spill Code Placement Analysis", true, true) 00048 INITIALIZE_PASS_DEPENDENCY(EdgeBundles) 00049 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) 00050 INITIALIZE_PASS_END(SpillPlacement, "spill-code-placement", 00051 "Spill Code Placement Analysis", true, true) 00052 00053 char &llvm::SpillPlacementID = SpillPlacement::ID; 00054 00055 void SpillPlacement::getAnalysisUsage(AnalysisUsage &AU) const { 00056 AU.setPreservesAll(); 00057 AU.addRequired<MachineBlockFrequencyInfo>(); 00058 AU.addRequiredTransitive<EdgeBundles>(); 00059 AU.addRequiredTransitive<MachineLoopInfo>(); 00060 MachineFunctionPass::getAnalysisUsage(AU); 00061 } 00062 00063 namespace { 00064 static BlockFrequency Threshold; 00065 } 00066 00067 /// Decision threshold. A node gets the output value 0 if the weighted sum of 00068 /// its inputs falls in the open interval (-Threshold;Threshold). 00069 static BlockFrequency getThreshold() { return Threshold; } 00070 00071 /// \brief Set the threshold for a given entry frequency. 00072 /// 00073 /// Set the threshold relative to \c Entry. Since the threshold is used as a 00074 /// bound on the open interval (-Threshold;Threshold), 1 is the minimum 00075 /// threshold. 00076 static void setThreshold(const BlockFrequency &Entry) { 00077 // Apparently 2 is a good threshold when Entry==2^14, but we need to scale 00078 // it. Divide by 2^13, rounding as appropriate. 00079 uint64_t Freq = Entry.getFrequency(); 00080 uint64_t Scaled = (Freq >> 13) + bool(Freq & (1 << 12)); 00081 Threshold = std::max(UINT64_C(1), Scaled); 00082 } 00083 00084 /// Node - Each edge bundle corresponds to a Hopfield node. 00085 /// 00086 /// The node contains precomputed frequency data that only depends on the CFG, 00087 /// but Bias and Links are computed each time placeSpills is called. 00088 /// 00089 /// The node Value is positive when the variable should be in a register. The 00090 /// value can change when linked nodes change, but convergence is very fast 00091 /// because all weights are positive. 00092 /// 00093 struct SpillPlacement::Node { 00094 /// BiasN - Sum of blocks that prefer a spill. 00095 BlockFrequency BiasN; 00096 /// BiasP - Sum of blocks that prefer a register. 00097 BlockFrequency BiasP; 00098 00099 /// Value - Output value of this node computed from the Bias and links. 00100 /// This is always on of the values {-1, 0, 1}. A positive number means the 00101 /// variable should go in a register through this bundle. 00102 int Value; 00103 00104 typedef SmallVector<std::pair<BlockFrequency, unsigned>, 4> LinkVector; 00105 00106 /// Links - (Weight, BundleNo) for all transparent blocks connecting to other 00107 /// bundles. The weights are all positive block frequencies. 00108 LinkVector Links; 00109 00110 /// SumLinkWeights - Cached sum of the weights of all links + ThresHold. 00111 BlockFrequency SumLinkWeights; 00112 00113 /// preferReg - Return true when this node prefers to be in a register. 00114 bool preferReg() const { 00115 // Undecided nodes (Value==0) go on the stack. 00116 return Value > 0; 00117 } 00118 00119 /// mustSpill - Return True if this node is so biased that it must spill. 00120 bool mustSpill() const { 00121 // We must spill if Bias < -sum(weights) or the MustSpill flag was set. 00122 // BiasN is saturated when MustSpill is set, make sure this still returns 00123 // true when the RHS saturates. Note that SumLinkWeights includes Threshold. 00124 return BiasN >= BiasP + SumLinkWeights; 00125 } 00126 00127 /// clear - Reset per-query data, but preserve frequencies that only depend on 00128 // the CFG. 00129 void clear() { 00130 BiasN = BiasP = Value = 0; 00131 SumLinkWeights = getThreshold(); 00132 Links.clear(); 00133 } 00134 00135 /// addLink - Add a link to bundle b with weight w. 00136 void addLink(unsigned b, BlockFrequency w) { 00137 // Update cached sum. 00138 SumLinkWeights += w; 00139 00140 // There can be multiple links to the same bundle, add them up. 00141 for (LinkVector::iterator I = Links.begin(), E = Links.end(); I != E; ++I) 00142 if (I->second == b) { 00143 I->first += w; 00144 return; 00145 } 00146 // This must be the first link to b. 00147 Links.push_back(std::make_pair(w, b)); 00148 } 00149 00150 /// addBias - Bias this node. 00151 void addBias(BlockFrequency freq, BorderConstraint direction) { 00152 switch (direction) { 00153 default: 00154 break; 00155 case PrefReg: 00156 BiasP += freq; 00157 break; 00158 case PrefSpill: 00159 BiasN += freq; 00160 break; 00161 case MustSpill: 00162 BiasN = BlockFrequency::getMaxFrequency(); 00163 break; 00164 } 00165 } 00166 00167 /// update - Recompute Value from Bias and Links. Return true when node 00168 /// preference changes. 00169 bool update(const Node nodes[]) { 00170 // Compute the weighted sum of inputs. 00171 BlockFrequency SumN = BiasN; 00172 BlockFrequency SumP = BiasP; 00173 for (LinkVector::iterator I = Links.begin(), E = Links.end(); I != E; ++I) { 00174 if (nodes[I->second].Value == -1) 00175 SumN += I->first; 00176 else if (nodes[I->second].Value == 1) 00177 SumP += I->first; 00178 } 00179 00180 // Each weighted sum is going to be less than the total frequency of the 00181 // bundle. Ideally, we should simply set Value = sign(SumP - SumN), but we 00182 // will add a dead zone around 0 for two reasons: 00183 // 00184 // 1. It avoids arbitrary bias when all links are 0 as is possible during 00185 // initial iterations. 00186 // 2. It helps tame rounding errors when the links nominally sum to 0. 00187 // 00188 bool Before = preferReg(); 00189 if (SumN >= SumP + getThreshold()) 00190 Value = -1; 00191 else if (SumP >= SumN + getThreshold()) 00192 Value = 1; 00193 else 00194 Value = 0; 00195 return Before != preferReg(); 00196 } 00197 }; 00198 00199 bool SpillPlacement::runOnMachineFunction(MachineFunction &mf) { 00200 MF = &mf; 00201 bundles = &getAnalysis<EdgeBundles>(); 00202 loops = &getAnalysis<MachineLoopInfo>(); 00203 00204 assert(!nodes && "Leaking node array"); 00205 nodes = new Node[bundles->getNumBundles()]; 00206 00207 // Compute total ingoing and outgoing block frequencies for all bundles. 00208 BlockFrequencies.resize(mf.getNumBlockIDs()); 00209 MBFI = &getAnalysis<MachineBlockFrequencyInfo>(); 00210 setThreshold(MBFI->getEntryFreq()); 00211 for (MachineFunction::iterator I = mf.begin(), E = mf.end(); I != E; ++I) { 00212 unsigned Num = I->getNumber(); 00213 BlockFrequencies[Num] = MBFI->getBlockFreq(I); 00214 } 00215 00216 // We never change the function. 00217 return false; 00218 } 00219 00220 void SpillPlacement::releaseMemory() { 00221 delete[] nodes; 00222 nodes = nullptr; 00223 } 00224 00225 /// activate - mark node n as active if it wasn't already. 00226 void SpillPlacement::activate(unsigned n) { 00227 if (ActiveNodes->test(n)) 00228 return; 00229 ActiveNodes->set(n); 00230 nodes[n].clear(); 00231 00232 // Very large bundles usually come from big switches, indirect branches, 00233 // landing pads, or loops with many 'continue' statements. It is difficult to 00234 // allocate registers when so many different blocks are involved. 00235 // 00236 // Give a small negative bias to large bundles such that a substantial 00237 // fraction of the connected blocks need to be interested before we consider 00238 // expanding the region through the bundle. This helps compile time by 00239 // limiting the number of blocks visited and the number of links in the 00240 // Hopfield network. 00241 if (bundles->getBlocks(n).size() > 100) { 00242 nodes[n].BiasP = 0; 00243 nodes[n].BiasN = (MBFI->getEntryFreq() / 16); 00244 } 00245 } 00246 00247 00248 /// addConstraints - Compute node biases and weights from a set of constraints. 00249 /// Set a bit in NodeMask for each active node. 00250 void SpillPlacement::addConstraints(ArrayRef<BlockConstraint> LiveBlocks) { 00251 for (ArrayRef<BlockConstraint>::iterator I = LiveBlocks.begin(), 00252 E = LiveBlocks.end(); I != E; ++I) { 00253 BlockFrequency Freq = BlockFrequencies[I->Number]; 00254 00255 // Live-in to block? 00256 if (I->Entry != DontCare) { 00257 unsigned ib = bundles->getBundle(I->Number, 0); 00258 activate(ib); 00259 nodes[ib].addBias(Freq, I->Entry); 00260 } 00261 00262 // Live-out from block? 00263 if (I->Exit != DontCare) { 00264 unsigned ob = bundles->getBundle(I->Number, 1); 00265 activate(ob); 00266 nodes[ob].addBias(Freq, I->Exit); 00267 } 00268 } 00269 } 00270 00271 /// addPrefSpill - Same as addConstraints(PrefSpill) 00272 void SpillPlacement::addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong) { 00273 for (ArrayRef<unsigned>::iterator I = Blocks.begin(), E = Blocks.end(); 00274 I != E; ++I) { 00275 BlockFrequency Freq = BlockFrequencies[*I]; 00276 if (Strong) 00277 Freq += Freq; 00278 unsigned ib = bundles->getBundle(*I, 0); 00279 unsigned ob = bundles->getBundle(*I, 1); 00280 activate(ib); 00281 activate(ob); 00282 nodes[ib].addBias(Freq, PrefSpill); 00283 nodes[ob].addBias(Freq, PrefSpill); 00284 } 00285 } 00286 00287 void SpillPlacement::addLinks(ArrayRef<unsigned> Links) { 00288 for (ArrayRef<unsigned>::iterator I = Links.begin(), E = Links.end(); I != E; 00289 ++I) { 00290 unsigned Number = *I; 00291 unsigned ib = bundles->getBundle(Number, 0); 00292 unsigned ob = bundles->getBundle(Number, 1); 00293 00294 // Ignore self-loops. 00295 if (ib == ob) 00296 continue; 00297 activate(ib); 00298 activate(ob); 00299 if (nodes[ib].Links.empty() && !nodes[ib].mustSpill()) 00300 Linked.push_back(ib); 00301 if (nodes[ob].Links.empty() && !nodes[ob].mustSpill()) 00302 Linked.push_back(ob); 00303 BlockFrequency Freq = BlockFrequencies[Number]; 00304 nodes[ib].addLink(ob, Freq); 00305 nodes[ob].addLink(ib, Freq); 00306 } 00307 } 00308 00309 bool SpillPlacement::scanActiveBundles() { 00310 Linked.clear(); 00311 RecentPositive.clear(); 00312 for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) { 00313 nodes[n].update(nodes); 00314 // A node that must spill, or a node without any links is not going to 00315 // change its value ever again, so exclude it from iterations. 00316 if (nodes[n].mustSpill()) 00317 continue; 00318 if (!nodes[n].Links.empty()) 00319 Linked.push_back(n); 00320 if (nodes[n].preferReg()) 00321 RecentPositive.push_back(n); 00322 } 00323 return !RecentPositive.empty(); 00324 } 00325 00326 /// iterate - Repeatedly update the Hopfield nodes until stability or the 00327 /// maximum number of iterations is reached. 00328 /// @param Linked - Numbers of linked nodes that need updating. 00329 void SpillPlacement::iterate() { 00330 // First update the recently positive nodes. They have likely received new 00331 // negative bias that will turn them off. 00332 while (!RecentPositive.empty()) 00333 nodes[RecentPositive.pop_back_val()].update(nodes); 00334 00335 if (Linked.empty()) 00336 return; 00337 00338 // Run up to 10 iterations. The edge bundle numbering is closely related to 00339 // basic block numbering, so there is a strong tendency towards chains of 00340 // linked nodes with sequential numbers. By scanning the linked nodes 00341 // backwards and forwards, we make it very likely that a single node can 00342 // affect the entire network in a single iteration. That means very fast 00343 // convergence, usually in a single iteration. 00344 for (unsigned iteration = 0; iteration != 10; ++iteration) { 00345 // Scan backwards, skipping the last node when iteration is not zero. When 00346 // iteration is not zero, the last node was just updated. 00347 bool Changed = false; 00348 for (SmallVectorImpl<unsigned>::const_reverse_iterator I = 00349 iteration == 0 ? Linked.rbegin() : std::next(Linked.rbegin()), 00350 E = Linked.rend(); I != E; ++I) { 00351 unsigned n = *I; 00352 if (nodes[n].update(nodes)) { 00353 Changed = true; 00354 if (nodes[n].preferReg()) 00355 RecentPositive.push_back(n); 00356 } 00357 } 00358 if (!Changed || !RecentPositive.empty()) 00359 return; 00360 00361 // Scan forwards, skipping the first node which was just updated. 00362 Changed = false; 00363 for (SmallVectorImpl<unsigned>::const_iterator I = 00364 std::next(Linked.begin()), E = Linked.end(); I != E; ++I) { 00365 unsigned n = *I; 00366 if (nodes[n].update(nodes)) { 00367 Changed = true; 00368 if (nodes[n].preferReg()) 00369 RecentPositive.push_back(n); 00370 } 00371 } 00372 if (!Changed || !RecentPositive.empty()) 00373 return; 00374 } 00375 } 00376 00377 void SpillPlacement::prepare(BitVector &RegBundles) { 00378 Linked.clear(); 00379 RecentPositive.clear(); 00380 // Reuse RegBundles as our ActiveNodes vector. 00381 ActiveNodes = &RegBundles; 00382 ActiveNodes->clear(); 00383 ActiveNodes->resize(bundles->getNumBundles()); 00384 } 00385 00386 bool 00387 SpillPlacement::finish() { 00388 assert(ActiveNodes && "Call prepare() first"); 00389 00390 // Write preferences back to ActiveNodes. 00391 bool Perfect = true; 00392 for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) 00393 if (!nodes[n].preferReg()) { 00394 ActiveNodes->reset(n); 00395 Perfect = false; 00396 } 00397 ActiveNodes = nullptr; 00398 return Perfect; 00399 }