1*a06bfe05SJan Sjodin //===- AMDGPUMachineCFGStructurizer.cpp - Machine code if conversion pass. ===// 2*a06bfe05SJan Sjodin // 3*a06bfe05SJan Sjodin // The LLVM Compiler Infrastructure 4*a06bfe05SJan Sjodin // 5*a06bfe05SJan Sjodin // This file is distributed under the University of Illinois Open Source 6*a06bfe05SJan Sjodin // License. See LICENSE.TXT for details. 7*a06bfe05SJan Sjodin // 8*a06bfe05SJan Sjodin //===----------------------------------------------------------------------===// 9*a06bfe05SJan Sjodin // 10*a06bfe05SJan Sjodin // This file implements the machine instruction level CFG structurizer pass. 11*a06bfe05SJan Sjodin // 12*a06bfe05SJan Sjodin //===----------------------------------------------------------------------===// 13*a06bfe05SJan Sjodin 14*a06bfe05SJan Sjodin #include "AMDGPU.h" 15*a06bfe05SJan Sjodin #include "SIInstrInfo.h" 16*a06bfe05SJan Sjodin #include "AMDGPUSubtarget.h" 17*a06bfe05SJan Sjodin #include "llvm/ADT/DenseSet.h" 18*a06bfe05SJan Sjodin #include "llvm/ADT/PostOrderIterator.h" 19*a06bfe05SJan Sjodin #include "llvm/ADT/SetVector.h" 20*a06bfe05SJan Sjodin #include "llvm/ADT/SmallPtrSet.h" 21*a06bfe05SJan Sjodin #include "llvm/ADT/SmallVector.h" 22*a06bfe05SJan Sjodin #include "llvm/Analysis/CFG.h" 23*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineBasicBlock.h" 24*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineFunctionPass.h" 25*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineInstr.h" 26*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineInstrBuilder.h" 27*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineRegionInfo.h" 28*a06bfe05SJan Sjodin #include "llvm/CodeGen/MachineRegisterInfo.h" 29*a06bfe05SJan Sjodin #include "llvm/CodeGen/Passes.h" 30*a06bfe05SJan Sjodin #include "llvm/IR/DebugLoc.h" 31*a06bfe05SJan Sjodin #include "llvm/Support/Debug.h" 32*a06bfe05SJan Sjodin #include "llvm/Target/TargetInstrInfo.h" 33*a06bfe05SJan Sjodin #include "llvm/Target/TargetLowering.h" 34*a06bfe05SJan Sjodin #include "llvm/Target/TargetSubtargetInfo.h" 35*a06bfe05SJan Sjodin #include <tuple> 36*a06bfe05SJan Sjodin using namespace llvm; 37*a06bfe05SJan Sjodin 38*a06bfe05SJan Sjodin #define DEBUG_TYPE "amdgpucfgstructurizer" 39*a06bfe05SJan Sjodin 40*a06bfe05SJan Sjodin namespace { 41*a06bfe05SJan Sjodin class PHILinearizeDestIterator; 42*a06bfe05SJan Sjodin 43*a06bfe05SJan Sjodin class PHILinearize { 44*a06bfe05SJan Sjodin friend class PHILinearizeDestIterator; 45*a06bfe05SJan Sjodin 46*a06bfe05SJan Sjodin public: 47*a06bfe05SJan Sjodin typedef std::pair<unsigned, MachineBasicBlock *> PHISourceT; 48*a06bfe05SJan Sjodin 49*a06bfe05SJan Sjodin private: 50*a06bfe05SJan Sjodin typedef DenseSet<PHISourceT> PHISourcesT; 51*a06bfe05SJan Sjodin typedef struct { 52*a06bfe05SJan Sjodin unsigned DestReg; 53*a06bfe05SJan Sjodin DebugLoc DL; 54*a06bfe05SJan Sjodin PHISourcesT Sources; 55*a06bfe05SJan Sjodin } PHIInfoElementT; 56*a06bfe05SJan Sjodin typedef SmallPtrSet<PHIInfoElementT *, 2> PHIInfoT; 57*a06bfe05SJan Sjodin PHIInfoT PHIInfo; 58*a06bfe05SJan Sjodin 59*a06bfe05SJan Sjodin static unsigned phiInfoElementGetDest(PHIInfoElementT *Info); 60*a06bfe05SJan Sjodin static void phiInfoElementSetDef(PHIInfoElementT *Info, unsigned NewDef); 61*a06bfe05SJan Sjodin static DebugLoc phiInfoElementGetDebugLoc(PHIInfoElementT *Info); 62*a06bfe05SJan Sjodin static PHISourcesT &phiInfoElementGetSources(PHIInfoElementT *Info); 63*a06bfe05SJan Sjodin static void phiInfoElementAddSource(PHIInfoElementT *Info, unsigned SourceReg, 64*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB); 65*a06bfe05SJan Sjodin static void phiInfoElementRemoveSource(PHIInfoElementT *Info, 66*a06bfe05SJan Sjodin unsigned SourceReg, 67*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB); 68*a06bfe05SJan Sjodin PHIInfoElementT *findPHIInfoElement(unsigned DestReg); 69*a06bfe05SJan Sjodin PHIInfoElementT *findPHIInfoElementFromSource(unsigned SourceReg, 70*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB); 71*a06bfe05SJan Sjodin 72*a06bfe05SJan Sjodin public: 73*a06bfe05SJan Sjodin bool findSourcesFromMBB(MachineBasicBlock *SourceMBB, 74*a06bfe05SJan Sjodin SmallVector<unsigned, 4> &Sources); 75*a06bfe05SJan Sjodin void addDest(unsigned DestReg, const DebugLoc &DL); 76*a06bfe05SJan Sjodin void replaceDef(unsigned OldDestReg, unsigned NewDestReg); 77*a06bfe05SJan Sjodin void deleteDef(unsigned DestReg); 78*a06bfe05SJan Sjodin void addSource(unsigned DestReg, unsigned SourceReg, 79*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB); 80*a06bfe05SJan Sjodin void removeSource(unsigned DestReg, unsigned SourceReg, 81*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB = nullptr); 82*a06bfe05SJan Sjodin bool findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB, 83*a06bfe05SJan Sjodin unsigned &DestReg); 84*a06bfe05SJan Sjodin bool isSource(unsigned Reg, MachineBasicBlock *SourceMBB = nullptr); 85*a06bfe05SJan Sjodin unsigned getNumSources(unsigned DestReg); 86*a06bfe05SJan Sjodin void dump(MachineRegisterInfo *MRI); 87*a06bfe05SJan Sjodin void clear(); 88*a06bfe05SJan Sjodin 89*a06bfe05SJan Sjodin typedef PHISourcesT::iterator source_iterator; 90*a06bfe05SJan Sjodin typedef PHILinearizeDestIterator dest_iterator; 91*a06bfe05SJan Sjodin 92*a06bfe05SJan Sjodin dest_iterator dests_begin(); 93*a06bfe05SJan Sjodin dest_iterator dests_end(); 94*a06bfe05SJan Sjodin 95*a06bfe05SJan Sjodin source_iterator sources_begin(unsigned Reg); 96*a06bfe05SJan Sjodin source_iterator sources_end(unsigned Reg); 97*a06bfe05SJan Sjodin }; 98*a06bfe05SJan Sjodin 99*a06bfe05SJan Sjodin class PHILinearizeDestIterator { 100*a06bfe05SJan Sjodin private: 101*a06bfe05SJan Sjodin PHILinearize::PHIInfoT::iterator Iter; 102*a06bfe05SJan Sjodin 103*a06bfe05SJan Sjodin public: 104*a06bfe05SJan Sjodin unsigned operator*() { return PHILinearize::phiInfoElementGetDest(*Iter); } 105*a06bfe05SJan Sjodin PHILinearizeDestIterator &operator++() { 106*a06bfe05SJan Sjodin ++Iter; 107*a06bfe05SJan Sjodin return *this; 108*a06bfe05SJan Sjodin } 109*a06bfe05SJan Sjodin bool operator==(const PHILinearizeDestIterator &I) const { 110*a06bfe05SJan Sjodin return I.Iter == Iter; 111*a06bfe05SJan Sjodin } 112*a06bfe05SJan Sjodin bool operator!=(const PHILinearizeDestIterator &I) const { 113*a06bfe05SJan Sjodin return I.Iter != Iter; 114*a06bfe05SJan Sjodin } 115*a06bfe05SJan Sjodin 116*a06bfe05SJan Sjodin PHILinearizeDestIterator(PHILinearize::PHIInfoT::iterator I) : Iter(I) {} 117*a06bfe05SJan Sjodin }; 118*a06bfe05SJan Sjodin 119*a06bfe05SJan Sjodin unsigned PHILinearize::phiInfoElementGetDest(PHIInfoElementT *Info) { 120*a06bfe05SJan Sjodin return Info->DestReg; 121*a06bfe05SJan Sjodin } 122*a06bfe05SJan Sjodin 123*a06bfe05SJan Sjodin void PHILinearize::phiInfoElementSetDef(PHIInfoElementT *Info, 124*a06bfe05SJan Sjodin unsigned NewDef) { 125*a06bfe05SJan Sjodin Info->DestReg = NewDef; 126*a06bfe05SJan Sjodin } 127*a06bfe05SJan Sjodin 128*a06bfe05SJan Sjodin DebugLoc PHILinearize::phiInfoElementGetDebugLoc(PHIInfoElementT *Info) { 129*a06bfe05SJan Sjodin return Info->DL; 130*a06bfe05SJan Sjodin } 131*a06bfe05SJan Sjodin 132*a06bfe05SJan Sjodin PHILinearize::PHISourcesT & 133*a06bfe05SJan Sjodin PHILinearize::phiInfoElementGetSources(PHIInfoElementT *Info) { 134*a06bfe05SJan Sjodin return Info->Sources; 135*a06bfe05SJan Sjodin } 136*a06bfe05SJan Sjodin 137*a06bfe05SJan Sjodin void PHILinearize::phiInfoElementAddSource(PHIInfoElementT *Info, 138*a06bfe05SJan Sjodin unsigned SourceReg, 139*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB) { 140*a06bfe05SJan Sjodin // Assertion ensures we don't use the same SourceMBB for the 141*a06bfe05SJan Sjodin // sources, because we cannot have different registers with 142*a06bfe05SJan Sjodin // identical predecessors, but we can have the same register for 143*a06bfe05SJan Sjodin // multiple predecessors. 144*a06bfe05SJan Sjodin for (auto SI : phiInfoElementGetSources(Info)) { 145*a06bfe05SJan Sjodin assert((SI.second != SourceMBB || SourceReg == SI.first)); 146*a06bfe05SJan Sjodin } 147*a06bfe05SJan Sjodin 148*a06bfe05SJan Sjodin phiInfoElementGetSources(Info).insert(PHISourceT(SourceReg, SourceMBB)); 149*a06bfe05SJan Sjodin } 150*a06bfe05SJan Sjodin 151*a06bfe05SJan Sjodin void PHILinearize::phiInfoElementRemoveSource(PHIInfoElementT *Info, 152*a06bfe05SJan Sjodin unsigned SourceReg, 153*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB) { 154*a06bfe05SJan Sjodin auto &Sources = phiInfoElementGetSources(Info); 155*a06bfe05SJan Sjodin SmallVector<PHISourceT, 4> ElimiatedSources; 156*a06bfe05SJan Sjodin for (auto SI : Sources) { 157*a06bfe05SJan Sjodin if (SI.first == SourceReg && 158*a06bfe05SJan Sjodin (SI.second == nullptr || SI.second == SourceMBB)) { 159*a06bfe05SJan Sjodin ElimiatedSources.push_back(PHISourceT(SI.first, SI.second)); 160*a06bfe05SJan Sjodin } 161*a06bfe05SJan Sjodin } 162*a06bfe05SJan Sjodin 163*a06bfe05SJan Sjodin for (auto &Source : ElimiatedSources) { 164*a06bfe05SJan Sjodin Sources.erase(Source); 165*a06bfe05SJan Sjodin } 166*a06bfe05SJan Sjodin } 167*a06bfe05SJan Sjodin 168*a06bfe05SJan Sjodin PHILinearize::PHIInfoElementT * 169*a06bfe05SJan Sjodin PHILinearize::findPHIInfoElement(unsigned DestReg) { 170*a06bfe05SJan Sjodin for (auto I : PHIInfo) { 171*a06bfe05SJan Sjodin if (phiInfoElementGetDest(I) == DestReg) { 172*a06bfe05SJan Sjodin return I; 173*a06bfe05SJan Sjodin } 174*a06bfe05SJan Sjodin } 175*a06bfe05SJan Sjodin return nullptr; 176*a06bfe05SJan Sjodin } 177*a06bfe05SJan Sjodin 178*a06bfe05SJan Sjodin PHILinearize::PHIInfoElementT * 179*a06bfe05SJan Sjodin PHILinearize::findPHIInfoElementFromSource(unsigned SourceReg, 180*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB) { 181*a06bfe05SJan Sjodin for (auto I : PHIInfo) { 182*a06bfe05SJan Sjodin for (auto SI : phiInfoElementGetSources(I)) { 183*a06bfe05SJan Sjodin if (SI.first == SourceReg && 184*a06bfe05SJan Sjodin (SI.second == nullptr || SI.second == SourceMBB)) { 185*a06bfe05SJan Sjodin return I; 186*a06bfe05SJan Sjodin } 187*a06bfe05SJan Sjodin } 188*a06bfe05SJan Sjodin } 189*a06bfe05SJan Sjodin return nullptr; 190*a06bfe05SJan Sjodin } 191*a06bfe05SJan Sjodin 192*a06bfe05SJan Sjodin bool PHILinearize::findSourcesFromMBB(MachineBasicBlock *SourceMBB, 193*a06bfe05SJan Sjodin SmallVector<unsigned, 4> &Sources) { 194*a06bfe05SJan Sjodin bool FoundSource = false; 195*a06bfe05SJan Sjodin for (auto I : PHIInfo) { 196*a06bfe05SJan Sjodin for (auto SI : phiInfoElementGetSources(I)) { 197*a06bfe05SJan Sjodin if (SI.second == SourceMBB) { 198*a06bfe05SJan Sjodin FoundSource = true; 199*a06bfe05SJan Sjodin Sources.push_back(SI.first); 200*a06bfe05SJan Sjodin } 201*a06bfe05SJan Sjodin } 202*a06bfe05SJan Sjodin } 203*a06bfe05SJan Sjodin return FoundSource; 204*a06bfe05SJan Sjodin } 205*a06bfe05SJan Sjodin 206*a06bfe05SJan Sjodin void PHILinearize::addDest(unsigned DestReg, const DebugLoc &DL) { 207*a06bfe05SJan Sjodin assert(findPHIInfoElement(DestReg) == nullptr && "Dest already exsists"); 208*a06bfe05SJan Sjodin PHISourcesT EmptySet; 209*a06bfe05SJan Sjodin PHIInfoElementT *NewElement = new PHIInfoElementT(); 210*a06bfe05SJan Sjodin NewElement->DestReg = DestReg; 211*a06bfe05SJan Sjodin NewElement->DL = DL; 212*a06bfe05SJan Sjodin NewElement->Sources = EmptySet; 213*a06bfe05SJan Sjodin PHIInfo.insert(NewElement); 214*a06bfe05SJan Sjodin } 215*a06bfe05SJan Sjodin 216*a06bfe05SJan Sjodin void PHILinearize::replaceDef(unsigned OldDestReg, unsigned NewDestReg) { 217*a06bfe05SJan Sjodin phiInfoElementSetDef(findPHIInfoElement(OldDestReg), NewDestReg); 218*a06bfe05SJan Sjodin } 219*a06bfe05SJan Sjodin 220*a06bfe05SJan Sjodin void PHILinearize::deleteDef(unsigned DestReg) { 221*a06bfe05SJan Sjodin PHIInfoElementT *InfoElement = findPHIInfoElement(DestReg); 222*a06bfe05SJan Sjodin PHIInfo.erase(InfoElement); 223*a06bfe05SJan Sjodin delete InfoElement; 224*a06bfe05SJan Sjodin } 225*a06bfe05SJan Sjodin 226*a06bfe05SJan Sjodin void PHILinearize::addSource(unsigned DestReg, unsigned SourceReg, 227*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB) { 228*a06bfe05SJan Sjodin phiInfoElementAddSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB); 229*a06bfe05SJan Sjodin } 230*a06bfe05SJan Sjodin 231*a06bfe05SJan Sjodin void PHILinearize::removeSource(unsigned DestReg, unsigned SourceReg, 232*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB) { 233*a06bfe05SJan Sjodin phiInfoElementRemoveSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB); 234*a06bfe05SJan Sjodin } 235*a06bfe05SJan Sjodin 236*a06bfe05SJan Sjodin bool PHILinearize::findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB, 237*a06bfe05SJan Sjodin unsigned &DestReg) { 238*a06bfe05SJan Sjodin PHIInfoElementT *InfoElement = 239*a06bfe05SJan Sjodin findPHIInfoElementFromSource(SourceReg, SourceMBB); 240*a06bfe05SJan Sjodin if (InfoElement != nullptr) { 241*a06bfe05SJan Sjodin DestReg = phiInfoElementGetDest(InfoElement); 242*a06bfe05SJan Sjodin return true; 243*a06bfe05SJan Sjodin } 244*a06bfe05SJan Sjodin return false; 245*a06bfe05SJan Sjodin } 246*a06bfe05SJan Sjodin 247*a06bfe05SJan Sjodin bool PHILinearize::isSource(unsigned Reg, MachineBasicBlock *SourceMBB) { 248*a06bfe05SJan Sjodin unsigned DestReg; 249*a06bfe05SJan Sjodin return findDest(Reg, SourceMBB, DestReg); 250*a06bfe05SJan Sjodin } 251*a06bfe05SJan Sjodin 252*a06bfe05SJan Sjodin unsigned PHILinearize::getNumSources(unsigned DestReg) { 253*a06bfe05SJan Sjodin return phiInfoElementGetSources(findPHIInfoElement(DestReg)).size(); 254*a06bfe05SJan Sjodin } 255*a06bfe05SJan Sjodin 256*a06bfe05SJan Sjodin void PHILinearize::dump(MachineRegisterInfo *MRI) { 257*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); 258*a06bfe05SJan Sjodin dbgs() << "=PHIInfo Start=\n"; 259*a06bfe05SJan Sjodin for (auto PII : this->PHIInfo) { 260*a06bfe05SJan Sjodin PHIInfoElementT &Element = *PII; 261*a06bfe05SJan Sjodin dbgs() << "Dest: " << PrintReg(Element.DestReg, TRI) 262*a06bfe05SJan Sjodin << " Sources: {"; 263*a06bfe05SJan Sjodin for (auto &SI : Element.Sources) { 264*a06bfe05SJan Sjodin dbgs() << PrintReg(SI.first, TRI) << "(BB#" 265*a06bfe05SJan Sjodin << SI.second->getNumber() << "),"; 266*a06bfe05SJan Sjodin } 267*a06bfe05SJan Sjodin dbgs() << "}\n"; 268*a06bfe05SJan Sjodin } 269*a06bfe05SJan Sjodin dbgs() << "=PHIInfo End=\n"; 270*a06bfe05SJan Sjodin } 271*a06bfe05SJan Sjodin 272*a06bfe05SJan Sjodin void PHILinearize::clear() { PHIInfo = PHIInfoT(); } 273*a06bfe05SJan Sjodin 274*a06bfe05SJan Sjodin PHILinearize::dest_iterator PHILinearize::dests_begin() { 275*a06bfe05SJan Sjodin return PHILinearizeDestIterator(PHIInfo.begin()); 276*a06bfe05SJan Sjodin } 277*a06bfe05SJan Sjodin 278*a06bfe05SJan Sjodin PHILinearize::dest_iterator PHILinearize::dests_end() { 279*a06bfe05SJan Sjodin return PHILinearizeDestIterator(PHIInfo.end()); 280*a06bfe05SJan Sjodin } 281*a06bfe05SJan Sjodin 282*a06bfe05SJan Sjodin PHILinearize::source_iterator PHILinearize::sources_begin(unsigned Reg) { 283*a06bfe05SJan Sjodin auto InfoElement = findPHIInfoElement(Reg); 284*a06bfe05SJan Sjodin return phiInfoElementGetSources(InfoElement).begin(); 285*a06bfe05SJan Sjodin } 286*a06bfe05SJan Sjodin PHILinearize::source_iterator PHILinearize::sources_end(unsigned Reg) { 287*a06bfe05SJan Sjodin auto InfoElement = findPHIInfoElement(Reg); 288*a06bfe05SJan Sjodin return phiInfoElementGetSources(InfoElement).end(); 289*a06bfe05SJan Sjodin } 290*a06bfe05SJan Sjodin 291*a06bfe05SJan Sjodin class RegionMRT; 292*a06bfe05SJan Sjodin class MBBMRT; 293*a06bfe05SJan Sjodin 294*a06bfe05SJan Sjodin static unsigned getPHINumInputs(MachineInstr &PHI) { 295*a06bfe05SJan Sjodin assert(PHI.isPHI()); 296*a06bfe05SJan Sjodin return (PHI.getNumOperands() - 1) / 2; 297*a06bfe05SJan Sjodin } 298*a06bfe05SJan Sjodin 299*a06bfe05SJan Sjodin static MachineBasicBlock *getPHIPred(MachineInstr &PHI, unsigned Index) { 300*a06bfe05SJan Sjodin assert(PHI.isPHI()); 301*a06bfe05SJan Sjodin return PHI.getOperand(Index * 2 + 2).getMBB(); 302*a06bfe05SJan Sjodin } 303*a06bfe05SJan Sjodin 304*a06bfe05SJan Sjodin static void setPhiPred(MachineInstr &PHI, unsigned Index, 305*a06bfe05SJan Sjodin MachineBasicBlock *NewPred) { 306*a06bfe05SJan Sjodin PHI.getOperand(Index * 2 + 2).setMBB(NewPred); 307*a06bfe05SJan Sjodin } 308*a06bfe05SJan Sjodin 309*a06bfe05SJan Sjodin static unsigned getPHISourceReg(MachineInstr &PHI, unsigned Index) { 310*a06bfe05SJan Sjodin assert(PHI.isPHI()); 311*a06bfe05SJan Sjodin return PHI.getOperand(Index * 2 + 1).getReg(); 312*a06bfe05SJan Sjodin } 313*a06bfe05SJan Sjodin 314*a06bfe05SJan Sjodin static unsigned getPHIDestReg(MachineInstr &PHI) { 315*a06bfe05SJan Sjodin assert(PHI.isPHI()); 316*a06bfe05SJan Sjodin return PHI.getOperand(0).getReg(); 317*a06bfe05SJan Sjodin } 318*a06bfe05SJan Sjodin 319*a06bfe05SJan Sjodin class LinearizedRegion { 320*a06bfe05SJan Sjodin protected: 321*a06bfe05SJan Sjodin MachineBasicBlock *Entry; 322*a06bfe05SJan Sjodin // The exit block is part of the region, and is the last 323*a06bfe05SJan Sjodin // merge block before exiting the region. 324*a06bfe05SJan Sjodin MachineBasicBlock *Exit; 325*a06bfe05SJan Sjodin DenseSet<unsigned> LiveOuts; 326*a06bfe05SJan Sjodin SmallPtrSet<MachineBasicBlock *, 1> MBBs; 327*a06bfe05SJan Sjodin bool HasLoop; 328*a06bfe05SJan Sjodin LinearizedRegion *Parent; 329*a06bfe05SJan Sjodin RegionMRT *RMRT; 330*a06bfe05SJan Sjodin 331*a06bfe05SJan Sjodin void storeLiveOutReg(MachineBasicBlock *MBB, unsigned Reg, 332*a06bfe05SJan Sjodin MachineInstr *DefInstr, const MachineRegisterInfo *MRI, 333*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 334*a06bfe05SJan Sjodin 335*a06bfe05SJan Sjodin void storeLiveOutRegRegion(RegionMRT *Region, unsigned Reg, 336*a06bfe05SJan Sjodin MachineInstr *DefInstr, 337*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 338*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 339*a06bfe05SJan Sjodin PHILinearize &PHIInfo); 340*a06bfe05SJan Sjodin 341*a06bfe05SJan Sjodin void storeMBBLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 342*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo, 343*a06bfe05SJan Sjodin RegionMRT *TopRegion); 344*a06bfe05SJan Sjodin 345*a06bfe05SJan Sjodin void storeLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 346*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 347*a06bfe05SJan Sjodin 348*a06bfe05SJan Sjodin void storeLiveOuts(RegionMRT *Region, const MachineRegisterInfo *MRI, 349*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo, 350*a06bfe05SJan Sjodin RegionMRT *TopRegion = nullptr); 351*a06bfe05SJan Sjodin 352*a06bfe05SJan Sjodin public: 353*a06bfe05SJan Sjodin void setRegionMRT(RegionMRT *Region) { RMRT = Region; } 354*a06bfe05SJan Sjodin 355*a06bfe05SJan Sjodin RegionMRT *getRegionMRT() { return RMRT; } 356*a06bfe05SJan Sjodin 357*a06bfe05SJan Sjodin void setParent(LinearizedRegion *P) { Parent = P; } 358*a06bfe05SJan Sjodin 359*a06bfe05SJan Sjodin LinearizedRegion *getParent() { return Parent; } 360*a06bfe05SJan Sjodin 361*a06bfe05SJan Sjodin void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr); 362*a06bfe05SJan Sjodin 363*a06bfe05SJan Sjodin void setBBSelectRegIn(unsigned Reg); 364*a06bfe05SJan Sjodin 365*a06bfe05SJan Sjodin unsigned getBBSelectRegIn(); 366*a06bfe05SJan Sjodin 367*a06bfe05SJan Sjodin void setBBSelectRegOut(unsigned Reg, bool IsLiveOut); 368*a06bfe05SJan Sjodin 369*a06bfe05SJan Sjodin unsigned getBBSelectRegOut(); 370*a06bfe05SJan Sjodin 371*a06bfe05SJan Sjodin void setHasLoop(bool Value); 372*a06bfe05SJan Sjodin 373*a06bfe05SJan Sjodin bool getHasLoop(); 374*a06bfe05SJan Sjodin 375*a06bfe05SJan Sjodin void addLiveOut(unsigned VReg); 376*a06bfe05SJan Sjodin 377*a06bfe05SJan Sjodin void removeLiveOut(unsigned Reg); 378*a06bfe05SJan Sjodin 379*a06bfe05SJan Sjodin void replaceLiveOut(unsigned OldReg, unsigned NewReg); 380*a06bfe05SJan Sjodin 381*a06bfe05SJan Sjodin void replaceRegister(unsigned Register, unsigned NewRegister, 382*a06bfe05SJan Sjodin MachineRegisterInfo *MRI, bool ReplaceInside, 383*a06bfe05SJan Sjodin bool ReplaceOutside, bool IncludeLoopPHIs); 384*a06bfe05SJan Sjodin 385*a06bfe05SJan Sjodin void replaceRegisterInsideRegion(unsigned Register, unsigned NewRegister, 386*a06bfe05SJan Sjodin bool IncludeLoopPHIs, 387*a06bfe05SJan Sjodin MachineRegisterInfo *MRI); 388*a06bfe05SJan Sjodin 389*a06bfe05SJan Sjodin void replaceRegisterOutsideRegion(unsigned Register, unsigned NewRegister, 390*a06bfe05SJan Sjodin bool IncludeLoopPHIs, 391*a06bfe05SJan Sjodin MachineRegisterInfo *MRI); 392*a06bfe05SJan Sjodin 393*a06bfe05SJan Sjodin DenseSet<unsigned> *getLiveOuts(); 394*a06bfe05SJan Sjodin 395*a06bfe05SJan Sjodin void setEntry(MachineBasicBlock *NewEntry); 396*a06bfe05SJan Sjodin 397*a06bfe05SJan Sjodin MachineBasicBlock *getEntry(); 398*a06bfe05SJan Sjodin 399*a06bfe05SJan Sjodin void setExit(MachineBasicBlock *NewExit); 400*a06bfe05SJan Sjodin 401*a06bfe05SJan Sjodin MachineBasicBlock *getExit(); 402*a06bfe05SJan Sjodin 403*a06bfe05SJan Sjodin void addMBB(MachineBasicBlock *MBB); 404*a06bfe05SJan Sjodin 405*a06bfe05SJan Sjodin void addMBBs(LinearizedRegion *InnerRegion); 406*a06bfe05SJan Sjodin 407*a06bfe05SJan Sjodin bool contains(MachineBasicBlock *MBB); 408*a06bfe05SJan Sjodin 409*a06bfe05SJan Sjodin bool isLiveOut(unsigned Reg); 410*a06bfe05SJan Sjodin 411*a06bfe05SJan Sjodin bool hasNoDef(unsigned Reg, MachineRegisterInfo *MRI); 412*a06bfe05SJan Sjodin 413*a06bfe05SJan Sjodin void removeFalseRegisterKills(MachineRegisterInfo *MRI); 414*a06bfe05SJan Sjodin 415*a06bfe05SJan Sjodin void initLiveOut(RegionMRT *Region, const MachineRegisterInfo *MRI, 416*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 417*a06bfe05SJan Sjodin 418*a06bfe05SJan Sjodin LinearizedRegion(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 419*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 420*a06bfe05SJan Sjodin 421*a06bfe05SJan Sjodin LinearizedRegion(); 422*a06bfe05SJan Sjodin 423*a06bfe05SJan Sjodin ~LinearizedRegion(); 424*a06bfe05SJan Sjodin }; 425*a06bfe05SJan Sjodin 426*a06bfe05SJan Sjodin class MRT { 427*a06bfe05SJan Sjodin protected: 428*a06bfe05SJan Sjodin RegionMRT *Parent; 429*a06bfe05SJan Sjodin unsigned BBSelectRegIn; 430*a06bfe05SJan Sjodin unsigned BBSelectRegOut; 431*a06bfe05SJan Sjodin 432*a06bfe05SJan Sjodin public: 433*a06bfe05SJan Sjodin unsigned getBBSelectRegIn() { return BBSelectRegIn; } 434*a06bfe05SJan Sjodin 435*a06bfe05SJan Sjodin unsigned getBBSelectRegOut() { return BBSelectRegOut; } 436*a06bfe05SJan Sjodin 437*a06bfe05SJan Sjodin void setBBSelectRegIn(unsigned Reg) { BBSelectRegIn = Reg; } 438*a06bfe05SJan Sjodin 439*a06bfe05SJan Sjodin void setBBSelectRegOut(unsigned Reg) { BBSelectRegOut = Reg; } 440*a06bfe05SJan Sjodin 441*a06bfe05SJan Sjodin virtual RegionMRT *getRegionMRT() { return nullptr; } 442*a06bfe05SJan Sjodin 443*a06bfe05SJan Sjodin virtual MBBMRT *getMBBMRT() { return nullptr; } 444*a06bfe05SJan Sjodin 445*a06bfe05SJan Sjodin bool isRegion() { return getRegionMRT() != nullptr; } 446*a06bfe05SJan Sjodin 447*a06bfe05SJan Sjodin bool isMBB() { return getMBBMRT() != nullptr; } 448*a06bfe05SJan Sjodin 449*a06bfe05SJan Sjodin bool isRoot() { return Parent == nullptr; } 450*a06bfe05SJan Sjodin 451*a06bfe05SJan Sjodin void setParent(RegionMRT *Region) { Parent = Region; } 452*a06bfe05SJan Sjodin 453*a06bfe05SJan Sjodin RegionMRT *getParent() { return Parent; } 454*a06bfe05SJan Sjodin 455*a06bfe05SJan Sjodin static MachineBasicBlock * 456*a06bfe05SJan Sjodin initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo, 457*a06bfe05SJan Sjodin DenseMap<MachineRegion *, RegionMRT *> &RegionMap); 458*a06bfe05SJan Sjodin 459*a06bfe05SJan Sjodin static RegionMRT *buildMRT(MachineFunction &MF, 460*a06bfe05SJan Sjodin const MachineRegionInfo *RegionInfo, 461*a06bfe05SJan Sjodin const SIInstrInfo *TII, 462*a06bfe05SJan Sjodin MachineRegisterInfo *MRI); 463*a06bfe05SJan Sjodin 464*a06bfe05SJan Sjodin virtual void dump(const TargetRegisterInfo *TRI, int depth = 0) = 0; 465*a06bfe05SJan Sjodin 466*a06bfe05SJan Sjodin void dumpDepth(int depth) { 467*a06bfe05SJan Sjodin for (int i = depth; i > 0; --i) { 468*a06bfe05SJan Sjodin dbgs() << " "; 469*a06bfe05SJan Sjodin } 470*a06bfe05SJan Sjodin } 471*a06bfe05SJan Sjodin 472*a06bfe05SJan Sjodin virtual ~MRT() {} 473*a06bfe05SJan Sjodin }; 474*a06bfe05SJan Sjodin 475*a06bfe05SJan Sjodin class MBBMRT : public MRT { 476*a06bfe05SJan Sjodin MachineBasicBlock *MBB; 477*a06bfe05SJan Sjodin 478*a06bfe05SJan Sjodin public: 479*a06bfe05SJan Sjodin virtual MBBMRT *getMBBMRT() { return this; } 480*a06bfe05SJan Sjodin 481*a06bfe05SJan Sjodin MachineBasicBlock *getMBB() { return MBB; } 482*a06bfe05SJan Sjodin 483*a06bfe05SJan Sjodin virtual void dump(const TargetRegisterInfo *TRI, int depth = 0) { 484*a06bfe05SJan Sjodin dumpDepth(depth); 485*a06bfe05SJan Sjodin dbgs() << "MBB: " << getMBB()->getNumber(); 486*a06bfe05SJan Sjodin dbgs() << " In: " << PrintReg(getBBSelectRegIn(), TRI); 487*a06bfe05SJan Sjodin dbgs() << ", Out: " << PrintReg(getBBSelectRegOut(), TRI) << "\n"; 488*a06bfe05SJan Sjodin } 489*a06bfe05SJan Sjodin 490*a06bfe05SJan Sjodin MBBMRT(MachineBasicBlock *BB) : MBB(BB) { 491*a06bfe05SJan Sjodin setParent(nullptr); 492*a06bfe05SJan Sjodin setBBSelectRegOut(0); 493*a06bfe05SJan Sjodin setBBSelectRegIn(0); 494*a06bfe05SJan Sjodin } 495*a06bfe05SJan Sjodin }; 496*a06bfe05SJan Sjodin 497*a06bfe05SJan Sjodin class RegionMRT : public MRT { 498*a06bfe05SJan Sjodin protected: 499*a06bfe05SJan Sjodin MachineRegion *Region; 500*a06bfe05SJan Sjodin LinearizedRegion *LRegion; 501*a06bfe05SJan Sjodin MachineBasicBlock *Succ; 502*a06bfe05SJan Sjodin 503*a06bfe05SJan Sjodin SetVector<MRT *> Children; 504*a06bfe05SJan Sjodin 505*a06bfe05SJan Sjodin public: 506*a06bfe05SJan Sjodin virtual RegionMRT *getRegionMRT() { return this; } 507*a06bfe05SJan Sjodin 508*a06bfe05SJan Sjodin void setLinearizedRegion(LinearizedRegion *LinearizeRegion) { 509*a06bfe05SJan Sjodin LRegion = LinearizeRegion; 510*a06bfe05SJan Sjodin } 511*a06bfe05SJan Sjodin 512*a06bfe05SJan Sjodin LinearizedRegion *getLinearizedRegion() { return LRegion; } 513*a06bfe05SJan Sjodin 514*a06bfe05SJan Sjodin MachineRegion *getMachineRegion() { return Region; } 515*a06bfe05SJan Sjodin 516*a06bfe05SJan Sjodin unsigned getInnerOutputRegister() { 517*a06bfe05SJan Sjodin return (*(Children.begin()))->getBBSelectRegOut(); 518*a06bfe05SJan Sjodin } 519*a06bfe05SJan Sjodin 520*a06bfe05SJan Sjodin void addChild(MRT *Tree) { Children.insert(Tree); } 521*a06bfe05SJan Sjodin 522*a06bfe05SJan Sjodin SetVector<MRT *> *getChildren() { return &Children; } 523*a06bfe05SJan Sjodin 524*a06bfe05SJan Sjodin virtual void dump(const TargetRegisterInfo *TRI, int depth = 0) { 525*a06bfe05SJan Sjodin dumpDepth(depth); 526*a06bfe05SJan Sjodin dbgs() << "Region: " << (void *)Region; 527*a06bfe05SJan Sjodin dbgs() << " In: " << PrintReg(getBBSelectRegIn(), TRI); 528*a06bfe05SJan Sjodin dbgs() << ", Out: " << PrintReg(getBBSelectRegOut(), TRI) << "\n"; 529*a06bfe05SJan Sjodin 530*a06bfe05SJan Sjodin dumpDepth(depth); 531*a06bfe05SJan Sjodin if (getSucc()) 532*a06bfe05SJan Sjodin dbgs() << "Succ: " << getSucc()->getNumber() << "\n"; 533*a06bfe05SJan Sjodin else 534*a06bfe05SJan Sjodin dbgs() << "Succ: none \n"; 535*a06bfe05SJan Sjodin for (auto MRTI : Children) { 536*a06bfe05SJan Sjodin MRTI->dump(TRI, depth + 1); 537*a06bfe05SJan Sjodin } 538*a06bfe05SJan Sjodin } 539*a06bfe05SJan Sjodin 540*a06bfe05SJan Sjodin MRT *getEntryTree() { return Children.back(); } 541*a06bfe05SJan Sjodin 542*a06bfe05SJan Sjodin MRT *getExitTree() { return Children.front(); } 543*a06bfe05SJan Sjodin 544*a06bfe05SJan Sjodin MachineBasicBlock *getEntry() { 545*a06bfe05SJan Sjodin MRT *Tree = Children.back(); 546*a06bfe05SJan Sjodin return (Tree->isRegion()) ? Tree->getRegionMRT()->getEntry() 547*a06bfe05SJan Sjodin : Tree->getMBBMRT()->getMBB(); 548*a06bfe05SJan Sjodin } 549*a06bfe05SJan Sjodin 550*a06bfe05SJan Sjodin MachineBasicBlock *getExit() { 551*a06bfe05SJan Sjodin MRT *Tree = Children.front(); 552*a06bfe05SJan Sjodin return (Tree->isRegion()) ? Tree->getRegionMRT()->getExit() 553*a06bfe05SJan Sjodin : Tree->getMBBMRT()->getMBB(); 554*a06bfe05SJan Sjodin } 555*a06bfe05SJan Sjodin 556*a06bfe05SJan Sjodin void setSucc(MachineBasicBlock *MBB) { Succ = MBB; } 557*a06bfe05SJan Sjodin 558*a06bfe05SJan Sjodin MachineBasicBlock *getSucc() { return Succ; } 559*a06bfe05SJan Sjodin 560*a06bfe05SJan Sjodin bool contains(MachineBasicBlock *MBB) { 561*a06bfe05SJan Sjodin for (auto CI : Children) { 562*a06bfe05SJan Sjodin if (CI->isMBB()) { 563*a06bfe05SJan Sjodin if (MBB == CI->getMBBMRT()->getMBB()) { 564*a06bfe05SJan Sjodin return true; 565*a06bfe05SJan Sjodin } 566*a06bfe05SJan Sjodin } else { 567*a06bfe05SJan Sjodin if (CI->getRegionMRT()->contains(MBB)) { 568*a06bfe05SJan Sjodin return true; 569*a06bfe05SJan Sjodin } else if (CI->getRegionMRT()->getLinearizedRegion() != nullptr && 570*a06bfe05SJan Sjodin CI->getRegionMRT()->getLinearizedRegion()->contains(MBB)) { 571*a06bfe05SJan Sjodin return true; 572*a06bfe05SJan Sjodin } 573*a06bfe05SJan Sjodin } 574*a06bfe05SJan Sjodin } 575*a06bfe05SJan Sjodin return false; 576*a06bfe05SJan Sjodin } 577*a06bfe05SJan Sjodin 578*a06bfe05SJan Sjodin void replaceLiveOutReg(unsigned Register, unsigned NewRegister) { 579*a06bfe05SJan Sjodin LinearizedRegion *LRegion = getLinearizedRegion(); 580*a06bfe05SJan Sjodin LRegion->replaceLiveOut(Register, NewRegister); 581*a06bfe05SJan Sjodin for (auto &CI : Children) { 582*a06bfe05SJan Sjodin if (CI->isRegion()) { 583*a06bfe05SJan Sjodin CI->getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 584*a06bfe05SJan Sjodin } 585*a06bfe05SJan Sjodin } 586*a06bfe05SJan Sjodin } 587*a06bfe05SJan Sjodin 588*a06bfe05SJan Sjodin RegionMRT(MachineRegion *MachineRegion) 589*a06bfe05SJan Sjodin : Region(MachineRegion), LRegion(nullptr), Succ(nullptr) { 590*a06bfe05SJan Sjodin setParent(nullptr); 591*a06bfe05SJan Sjodin setBBSelectRegOut(0); 592*a06bfe05SJan Sjodin setBBSelectRegIn(0); 593*a06bfe05SJan Sjodin } 594*a06bfe05SJan Sjodin 595*a06bfe05SJan Sjodin virtual ~RegionMRT() { 596*a06bfe05SJan Sjodin if (LRegion) { 597*a06bfe05SJan Sjodin delete LRegion; 598*a06bfe05SJan Sjodin } 599*a06bfe05SJan Sjodin 600*a06bfe05SJan Sjodin for (auto CI : Children) { 601*a06bfe05SJan Sjodin delete &(*CI); 602*a06bfe05SJan Sjodin } 603*a06bfe05SJan Sjodin } 604*a06bfe05SJan Sjodin }; 605*a06bfe05SJan Sjodin 606*a06bfe05SJan Sjodin static unsigned createBBSelectReg(const SIInstrInfo *TII, 607*a06bfe05SJan Sjodin MachineRegisterInfo *MRI) { 608*a06bfe05SJan Sjodin return MRI->createVirtualRegister(TII->getPreferredSelectRegClass(32)); 609*a06bfe05SJan Sjodin } 610*a06bfe05SJan Sjodin 611*a06bfe05SJan Sjodin MachineBasicBlock * 612*a06bfe05SJan Sjodin MRT::initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo, 613*a06bfe05SJan Sjodin DenseMap<MachineRegion *, RegionMRT *> &RegionMap) { 614*a06bfe05SJan Sjodin for (auto &MFI : MF) { 615*a06bfe05SJan Sjodin MachineBasicBlock *ExitMBB = &MFI; 616*a06bfe05SJan Sjodin if (ExitMBB->succ_size() == 0) { 617*a06bfe05SJan Sjodin return ExitMBB; 618*a06bfe05SJan Sjodin } 619*a06bfe05SJan Sjodin } 620*a06bfe05SJan Sjodin llvm_unreachable("CFG has no exit block"); 621*a06bfe05SJan Sjodin return nullptr; 622*a06bfe05SJan Sjodin } 623*a06bfe05SJan Sjodin 624*a06bfe05SJan Sjodin RegionMRT *MRT::buildMRT(MachineFunction &MF, 625*a06bfe05SJan Sjodin const MachineRegionInfo *RegionInfo, 626*a06bfe05SJan Sjodin const SIInstrInfo *TII, MachineRegisterInfo *MRI) { 627*a06bfe05SJan Sjodin SmallPtrSet<MachineRegion *, 4> PlacedRegions; 628*a06bfe05SJan Sjodin DenseMap<MachineRegion *, RegionMRT *> RegionMap; 629*a06bfe05SJan Sjodin MachineRegion *TopLevelRegion = RegionInfo->getTopLevelRegion(); 630*a06bfe05SJan Sjodin RegionMRT *Result = new RegionMRT(TopLevelRegion); 631*a06bfe05SJan Sjodin RegionMap[TopLevelRegion] = Result; 632*a06bfe05SJan Sjodin 633*a06bfe05SJan Sjodin // Insert the exit block first, we need it to be the merge node 634*a06bfe05SJan Sjodin // for the top level region. 635*a06bfe05SJan Sjodin MachineBasicBlock *Exit = initializeMRT(MF, RegionInfo, RegionMap); 636*a06bfe05SJan Sjodin 637*a06bfe05SJan Sjodin unsigned BBSelectRegIn = createBBSelectReg(TII, MRI); 638*a06bfe05SJan Sjodin MBBMRT *ExitMRT = new MBBMRT(Exit); 639*a06bfe05SJan Sjodin RegionMap[RegionInfo->getRegionFor(Exit)]->addChild(ExitMRT); 640*a06bfe05SJan Sjodin ExitMRT->setBBSelectRegIn(BBSelectRegIn); 641*a06bfe05SJan Sjodin 642*a06bfe05SJan Sjodin for (auto MBBI : post_order(&(MF.front()))) { 643*a06bfe05SJan Sjodin MachineBasicBlock *MBB = &(*MBBI); 644*a06bfe05SJan Sjodin 645*a06bfe05SJan Sjodin // Skip Exit since we already added it 646*a06bfe05SJan Sjodin if (MBB == Exit) { 647*a06bfe05SJan Sjodin continue; 648*a06bfe05SJan Sjodin } 649*a06bfe05SJan Sjodin 650*a06bfe05SJan Sjodin DEBUG(dbgs() << "Visiting BB#" << MBB->getNumber() << "\n"); 651*a06bfe05SJan Sjodin MBBMRT *NewMBB = new MBBMRT(MBB); 652*a06bfe05SJan Sjodin MachineRegion *Region = RegionInfo->getRegionFor(MBB); 653*a06bfe05SJan Sjodin 654*a06bfe05SJan Sjodin // Ensure we have the MRT region 655*a06bfe05SJan Sjodin if (RegionMap.count(Region) == 0) { 656*a06bfe05SJan Sjodin RegionMRT *NewMRTRegion = new RegionMRT(Region); 657*a06bfe05SJan Sjodin RegionMap[Region] = NewMRTRegion; 658*a06bfe05SJan Sjodin 659*a06bfe05SJan Sjodin // Ensure all parents are in the RegionMap 660*a06bfe05SJan Sjodin MachineRegion *Parent = Region->getParent(); 661*a06bfe05SJan Sjodin while (RegionMap.count(Parent) == 0) { 662*a06bfe05SJan Sjodin RegionMRT *NewMRTParent = new RegionMRT(Parent); 663*a06bfe05SJan Sjodin NewMRTParent->addChild(NewMRTRegion); 664*a06bfe05SJan Sjodin NewMRTRegion->setParent(NewMRTParent); 665*a06bfe05SJan Sjodin RegionMap[Parent] = NewMRTParent; 666*a06bfe05SJan Sjodin NewMRTRegion = NewMRTParent; 667*a06bfe05SJan Sjodin Parent = Parent->getParent(); 668*a06bfe05SJan Sjodin } 669*a06bfe05SJan Sjodin RegionMap[Parent]->addChild(NewMRTRegion); 670*a06bfe05SJan Sjodin NewMRTRegion->setParent(RegionMap[Parent]); 671*a06bfe05SJan Sjodin } 672*a06bfe05SJan Sjodin 673*a06bfe05SJan Sjodin // Add MBB to Region MRT 674*a06bfe05SJan Sjodin RegionMap[Region]->addChild(NewMBB); 675*a06bfe05SJan Sjodin NewMBB->setParent(RegionMap[Region]); 676*a06bfe05SJan Sjodin RegionMap[Region]->setSucc(Region->getExit()); 677*a06bfe05SJan Sjodin } 678*a06bfe05SJan Sjodin return Result; 679*a06bfe05SJan Sjodin } 680*a06bfe05SJan Sjodin 681*a06bfe05SJan Sjodin void LinearizedRegion::storeLiveOutReg(MachineBasicBlock *MBB, unsigned Reg, 682*a06bfe05SJan Sjodin MachineInstr *DefInstr, 683*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 684*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 685*a06bfe05SJan Sjodin PHILinearize &PHIInfo) { 686*a06bfe05SJan Sjodin if (TRI->isVirtualRegister(Reg)) { 687*a06bfe05SJan Sjodin DEBUG(dbgs() << "Considering Register: " << PrintReg(Reg, TRI) << "\n"); 688*a06bfe05SJan Sjodin // If this is a source register to a PHI we are chaining, it 689*a06bfe05SJan Sjodin // must be live out. 690*a06bfe05SJan Sjodin if (PHIInfo.isSource(Reg)) { 691*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (PHI): " << PrintReg(Reg, TRI) << "\n"); 692*a06bfe05SJan Sjodin addLiveOut(Reg); 693*a06bfe05SJan Sjodin } else { 694*a06bfe05SJan Sjodin // If this is live out of the MBB 695*a06bfe05SJan Sjodin for (auto &UI : MRI->use_operands(Reg)) { 696*a06bfe05SJan Sjodin if (UI.getParent()->getParent() != MBB) { 697*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (MBB BB#" << MBB->getNumber() 698*a06bfe05SJan Sjodin << "): " << PrintReg(Reg, TRI) << "\n"); 699*a06bfe05SJan Sjodin addLiveOut(Reg); 700*a06bfe05SJan Sjodin } else { 701*a06bfe05SJan Sjodin // If the use is in the same MBB we have to make sure 702*a06bfe05SJan Sjodin // it is after the def, otherwise it is live out in a loop 703*a06bfe05SJan Sjodin MachineInstr *UseInstr = UI.getParent(); 704*a06bfe05SJan Sjodin for (MachineBasicBlock::instr_iterator 705*a06bfe05SJan Sjodin MII = UseInstr->getIterator(), 706*a06bfe05SJan Sjodin MIE = UseInstr->getParent()->instr_end(); 707*a06bfe05SJan Sjodin MII != MIE; ++MII) { 708*a06bfe05SJan Sjodin if ((&(*MII)) == DefInstr) { 709*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (Loop): " << PrintReg(Reg, TRI) 710*a06bfe05SJan Sjodin << "\n"); 711*a06bfe05SJan Sjodin addLiveOut(Reg); 712*a06bfe05SJan Sjodin } 713*a06bfe05SJan Sjodin } 714*a06bfe05SJan Sjodin } 715*a06bfe05SJan Sjodin } 716*a06bfe05SJan Sjodin } 717*a06bfe05SJan Sjodin } 718*a06bfe05SJan Sjodin } 719*a06bfe05SJan Sjodin 720*a06bfe05SJan Sjodin void LinearizedRegion::storeLiveOutRegRegion(RegionMRT *Region, unsigned Reg, 721*a06bfe05SJan Sjodin MachineInstr *DefInstr, 722*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 723*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 724*a06bfe05SJan Sjodin PHILinearize &PHIInfo) { 725*a06bfe05SJan Sjodin if (TRI->isVirtualRegister(Reg)) { 726*a06bfe05SJan Sjodin DEBUG(dbgs() << "Considering Register: " << PrintReg(Reg, TRI) << "\n"); 727*a06bfe05SJan Sjodin for (auto &UI : MRI->use_operands(Reg)) { 728*a06bfe05SJan Sjodin if (!Region->contains(UI.getParent()->getParent())) { 729*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (Region " << (void *)Region 730*a06bfe05SJan Sjodin << "): " << PrintReg(Reg, TRI) << "\n"); 731*a06bfe05SJan Sjodin addLiveOut(Reg); 732*a06bfe05SJan Sjodin } 733*a06bfe05SJan Sjodin } 734*a06bfe05SJan Sjodin } 735*a06bfe05SJan Sjodin } 736*a06bfe05SJan Sjodin 737*a06bfe05SJan Sjodin void LinearizedRegion::storeLiveOuts(MachineBasicBlock *MBB, 738*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 739*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 740*a06bfe05SJan Sjodin PHILinearize &PHIInfo) { 741*a06bfe05SJan Sjodin DEBUG(dbgs() << "-Store Live Outs Begin (BB#" << MBB->getNumber() << ")-\n"); 742*a06bfe05SJan Sjodin for (auto &II : *MBB) { 743*a06bfe05SJan Sjodin for (auto &RI : II.defs()) { 744*a06bfe05SJan Sjodin storeLiveOutReg(MBB, RI.getReg(), RI.getParent(), MRI, TRI, PHIInfo); 745*a06bfe05SJan Sjodin } 746*a06bfe05SJan Sjodin for (auto &IRI : II.implicit_operands()) { 747*a06bfe05SJan Sjodin if (IRI.isDef()) { 748*a06bfe05SJan Sjodin storeLiveOutReg(MBB, IRI.getReg(), IRI.getParent(), MRI, TRI, PHIInfo); 749*a06bfe05SJan Sjodin } 750*a06bfe05SJan Sjodin } 751*a06bfe05SJan Sjodin } 752*a06bfe05SJan Sjodin 753*a06bfe05SJan Sjodin // If we have a successor with a PHI, source coming from this MBB we have to 754*a06bfe05SJan Sjodin // add the register as live out 755*a06bfe05SJan Sjodin for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), 756*a06bfe05SJan Sjodin E = MBB->succ_end(); 757*a06bfe05SJan Sjodin SI != E; ++SI) { 758*a06bfe05SJan Sjodin for (auto &II : *(*SI)) { 759*a06bfe05SJan Sjodin if (II.isPHI()) { 760*a06bfe05SJan Sjodin MachineInstr &PHI = II; 761*a06bfe05SJan Sjodin int numPreds = getPHINumInputs(PHI); 762*a06bfe05SJan Sjodin for (int i = 0; i < numPreds; ++i) { 763*a06bfe05SJan Sjodin if (getPHIPred(PHI, i) == MBB) { 764*a06bfe05SJan Sjodin unsigned PHIReg = getPHISourceReg(PHI, i); 765*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (PhiSource BB#" << MBB->getNumber() 766*a06bfe05SJan Sjodin << " -> BB#" << (*SI)->getNumber() 767*a06bfe05SJan Sjodin << "): " << PrintReg(PHIReg, TRI) << "\n"); 768*a06bfe05SJan Sjodin addLiveOut(PHIReg); 769*a06bfe05SJan Sjodin } 770*a06bfe05SJan Sjodin } 771*a06bfe05SJan Sjodin } 772*a06bfe05SJan Sjodin } 773*a06bfe05SJan Sjodin } 774*a06bfe05SJan Sjodin 775*a06bfe05SJan Sjodin DEBUG(dbgs() << "-Store Live Outs Endn-\n"); 776*a06bfe05SJan Sjodin } 777*a06bfe05SJan Sjodin 778*a06bfe05SJan Sjodin void LinearizedRegion::storeMBBLiveOuts(MachineBasicBlock *MBB, 779*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 780*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 781*a06bfe05SJan Sjodin PHILinearize &PHIInfo, 782*a06bfe05SJan Sjodin RegionMRT *TopRegion) { 783*a06bfe05SJan Sjodin for (auto &II : *MBB) { 784*a06bfe05SJan Sjodin for (auto &RI : II.defs()) { 785*a06bfe05SJan Sjodin storeLiveOutRegRegion(TopRegion, RI.getReg(), RI.getParent(), MRI, TRI, 786*a06bfe05SJan Sjodin PHIInfo); 787*a06bfe05SJan Sjodin } 788*a06bfe05SJan Sjodin for (auto &IRI : II.implicit_operands()) { 789*a06bfe05SJan Sjodin if (IRI.isDef()) { 790*a06bfe05SJan Sjodin storeLiveOutRegRegion(TopRegion, IRI.getReg(), IRI.getParent(), MRI, 791*a06bfe05SJan Sjodin TRI, PHIInfo); 792*a06bfe05SJan Sjodin } 793*a06bfe05SJan Sjodin } 794*a06bfe05SJan Sjodin } 795*a06bfe05SJan Sjodin } 796*a06bfe05SJan Sjodin 797*a06bfe05SJan Sjodin void LinearizedRegion::storeLiveOuts(RegionMRT *Region, 798*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 799*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 800*a06bfe05SJan Sjodin PHILinearize &PHIInfo, 801*a06bfe05SJan Sjodin RegionMRT *CurrentTopRegion) { 802*a06bfe05SJan Sjodin MachineBasicBlock *Exit = Region->getSucc(); 803*a06bfe05SJan Sjodin 804*a06bfe05SJan Sjodin RegionMRT *TopRegion = 805*a06bfe05SJan Sjodin CurrentTopRegion == nullptr ? Region : CurrentTopRegion; 806*a06bfe05SJan Sjodin 807*a06bfe05SJan Sjodin // Check if exit is end of function, if so, no live outs. 808*a06bfe05SJan Sjodin if (Exit == nullptr) 809*a06bfe05SJan Sjodin return; 810*a06bfe05SJan Sjodin 811*a06bfe05SJan Sjodin auto Children = Region->getChildren(); 812*a06bfe05SJan Sjodin for (auto CI : *Children) { 813*a06bfe05SJan Sjodin if (CI->isMBB()) { 814*a06bfe05SJan Sjodin auto MBB = CI->getMBBMRT()->getMBB(); 815*a06bfe05SJan Sjodin storeMBBLiveOuts(MBB, MRI, TRI, PHIInfo, TopRegion); 816*a06bfe05SJan Sjodin } else { 817*a06bfe05SJan Sjodin LinearizedRegion *SubRegion = CI->getRegionMRT()->getLinearizedRegion(); 818*a06bfe05SJan Sjodin // We should be limited to only store registers that are live out from the 819*a06bfe05SJan Sjodin // lineaized region 820*a06bfe05SJan Sjodin for (auto MBBI : SubRegion->MBBs) { 821*a06bfe05SJan Sjodin storeMBBLiveOuts(MBBI, MRI, TRI, PHIInfo, TopRegion); 822*a06bfe05SJan Sjodin } 823*a06bfe05SJan Sjodin } 824*a06bfe05SJan Sjodin } 825*a06bfe05SJan Sjodin 826*a06bfe05SJan Sjodin if (CurrentTopRegion == nullptr) { 827*a06bfe05SJan Sjodin auto Succ = Region->getSucc(); 828*a06bfe05SJan Sjodin for (auto &II : *Succ) { 829*a06bfe05SJan Sjodin if (II.isPHI()) { 830*a06bfe05SJan Sjodin MachineInstr &PHI = II; 831*a06bfe05SJan Sjodin int numPreds = getPHINumInputs(PHI); 832*a06bfe05SJan Sjodin for (int i = 0; i < numPreds; ++i) { 833*a06bfe05SJan Sjodin if (Region->contains(getPHIPred(PHI, i))) { 834*a06bfe05SJan Sjodin unsigned PHIReg = getPHISourceReg(PHI, i); 835*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add Region LiveOut (" << (void *)Region 836*a06bfe05SJan Sjodin << "): " << PrintReg(PHIReg, TRI) << "\n"); 837*a06bfe05SJan Sjodin addLiveOut(PHIReg); 838*a06bfe05SJan Sjodin } 839*a06bfe05SJan Sjodin } 840*a06bfe05SJan Sjodin } 841*a06bfe05SJan Sjodin } 842*a06bfe05SJan Sjodin } 843*a06bfe05SJan Sjodin } 844*a06bfe05SJan Sjodin 845*a06bfe05SJan Sjodin void LinearizedRegion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { 846*a06bfe05SJan Sjodin OS << "Linearized Region {"; 847*a06bfe05SJan Sjodin bool IsFirst = true; 848*a06bfe05SJan Sjodin for (const auto &MBB : MBBs) { 849*a06bfe05SJan Sjodin if (IsFirst) { 850*a06bfe05SJan Sjodin IsFirst = false; 851*a06bfe05SJan Sjodin } else { 852*a06bfe05SJan Sjodin OS << " ,"; 853*a06bfe05SJan Sjodin } 854*a06bfe05SJan Sjodin OS << MBB->getNumber(); 855*a06bfe05SJan Sjodin } 856*a06bfe05SJan Sjodin OS << "} (" << Entry->getNumber() << ", " 857*a06bfe05SJan Sjodin << (Exit == nullptr ? -1 : Exit->getNumber()) 858*a06bfe05SJan Sjodin << "): In:" << PrintReg(getBBSelectRegIn(), TRI) 859*a06bfe05SJan Sjodin << " Out:" << PrintReg(getBBSelectRegOut(), TRI) << " {"; 860*a06bfe05SJan Sjodin for (auto &LI : LiveOuts) { 861*a06bfe05SJan Sjodin OS << PrintReg(LI, TRI) << " "; 862*a06bfe05SJan Sjodin } 863*a06bfe05SJan Sjodin OS << "} \n"; 864*a06bfe05SJan Sjodin } 865*a06bfe05SJan Sjodin 866*a06bfe05SJan Sjodin unsigned LinearizedRegion::getBBSelectRegIn() { 867*a06bfe05SJan Sjodin return getRegionMRT()->getBBSelectRegIn(); 868*a06bfe05SJan Sjodin } 869*a06bfe05SJan Sjodin 870*a06bfe05SJan Sjodin unsigned LinearizedRegion::getBBSelectRegOut() { 871*a06bfe05SJan Sjodin return getRegionMRT()->getBBSelectRegOut(); 872*a06bfe05SJan Sjodin } 873*a06bfe05SJan Sjodin 874*a06bfe05SJan Sjodin void LinearizedRegion::setHasLoop(bool Value) { HasLoop = Value; } 875*a06bfe05SJan Sjodin 876*a06bfe05SJan Sjodin bool LinearizedRegion::getHasLoop() { return HasLoop; } 877*a06bfe05SJan Sjodin 878*a06bfe05SJan Sjodin void LinearizedRegion::addLiveOut(unsigned VReg) { LiveOuts.insert(VReg); } 879*a06bfe05SJan Sjodin 880*a06bfe05SJan Sjodin void LinearizedRegion::removeLiveOut(unsigned Reg) { 881*a06bfe05SJan Sjodin if (isLiveOut(Reg)) 882*a06bfe05SJan Sjodin LiveOuts.erase(Reg); 883*a06bfe05SJan Sjodin } 884*a06bfe05SJan Sjodin 885*a06bfe05SJan Sjodin void LinearizedRegion::replaceLiveOut(unsigned OldReg, unsigned NewReg) { 886*a06bfe05SJan Sjodin if (isLiveOut(OldReg)) { 887*a06bfe05SJan Sjodin removeLiveOut(OldReg); 888*a06bfe05SJan Sjodin addLiveOut(NewReg); 889*a06bfe05SJan Sjodin } 890*a06bfe05SJan Sjodin } 891*a06bfe05SJan Sjodin 892*a06bfe05SJan Sjodin void LinearizedRegion::replaceRegister(unsigned Register, unsigned NewRegister, 893*a06bfe05SJan Sjodin MachineRegisterInfo *MRI, 894*a06bfe05SJan Sjodin bool ReplaceInside, bool ReplaceOutside, 895*a06bfe05SJan Sjodin bool IncludeLoopPHI) { 896*a06bfe05SJan Sjodin assert(Register != NewRegister && "Cannot replace a reg with itself"); 897*a06bfe05SJan Sjodin 898*a06bfe05SJan Sjodin DEBUG(dbgs() << "Pepareing to replace register (region): " 899*a06bfe05SJan Sjodin << PrintReg(Register, MRI->getTargetRegisterInfo()) << " with " 900*a06bfe05SJan Sjodin << PrintReg(NewRegister, MRI->getTargetRegisterInfo()) << "\n"); 901*a06bfe05SJan Sjodin 902*a06bfe05SJan Sjodin // If we are replacing outside, we also need to update the LiveOuts 903*a06bfe05SJan Sjodin if (ReplaceOutside && 904*a06bfe05SJan Sjodin (isLiveOut(Register) || this->getParent()->isLiveOut(Register))) { 905*a06bfe05SJan Sjodin LinearizedRegion *Current = this; 906*a06bfe05SJan Sjodin while (Current != nullptr && Current->getEntry() != nullptr) { 907*a06bfe05SJan Sjodin DEBUG(dbgs() << "Region before register replace\n"); 908*a06bfe05SJan Sjodin DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 909*a06bfe05SJan Sjodin Current->replaceLiveOut(Register, NewRegister); 910*a06bfe05SJan Sjodin DEBUG(dbgs() << "Region after register replace\n"); 911*a06bfe05SJan Sjodin DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 912*a06bfe05SJan Sjodin Current = Current->getParent(); 913*a06bfe05SJan Sjodin } 914*a06bfe05SJan Sjodin } 915*a06bfe05SJan Sjodin 916*a06bfe05SJan Sjodin for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 917*a06bfe05SJan Sjodin E = MRI->reg_end(); 918*a06bfe05SJan Sjodin I != E;) { 919*a06bfe05SJan Sjodin MachineOperand &O = *I; 920*a06bfe05SJan Sjodin ++I; 921*a06bfe05SJan Sjodin 922*a06bfe05SJan Sjodin // We don't rewrite defs. 923*a06bfe05SJan Sjodin if (O.isDef()) 924*a06bfe05SJan Sjodin continue; 925*a06bfe05SJan Sjodin 926*a06bfe05SJan Sjodin bool IsInside = contains(O.getParent()->getParent()); 927*a06bfe05SJan Sjodin bool IsLoopPHI = IsInside && (O.getParent()->isPHI() && 928*a06bfe05SJan Sjodin O.getParent()->getParent() == getEntry()); 929*a06bfe05SJan Sjodin bool ShouldReplace = (IsInside && ReplaceInside) || 930*a06bfe05SJan Sjodin (!IsInside && ReplaceOutside) || 931*a06bfe05SJan Sjodin (IncludeLoopPHI && IsLoopPHI); 932*a06bfe05SJan Sjodin if (ShouldReplace) { 933*a06bfe05SJan Sjodin 934*a06bfe05SJan Sjodin if (TargetRegisterInfo::isPhysicalRegister(NewRegister)) { 935*a06bfe05SJan Sjodin DEBUG(dbgs() << "Trying to substitute physical register: " 936*a06bfe05SJan Sjodin << PrintReg(NewRegister, MRI->getTargetRegisterInfo()) 937*a06bfe05SJan Sjodin << "\n"); 938*a06bfe05SJan Sjodin llvm_unreachable("Cannot substitute physical registers"); 939*a06bfe05SJan Sjodin } else { 940*a06bfe05SJan Sjodin DEBUG(dbgs() << "Replacing register (region): " 941*a06bfe05SJan Sjodin << PrintReg(Register, MRI->getTargetRegisterInfo()) 942*a06bfe05SJan Sjodin << " with " 943*a06bfe05SJan Sjodin << PrintReg(NewRegister, MRI->getTargetRegisterInfo()) 944*a06bfe05SJan Sjodin << "\n"); 945*a06bfe05SJan Sjodin O.setReg(NewRegister); 946*a06bfe05SJan Sjodin } 947*a06bfe05SJan Sjodin } 948*a06bfe05SJan Sjodin } 949*a06bfe05SJan Sjodin } 950*a06bfe05SJan Sjodin 951*a06bfe05SJan Sjodin void LinearizedRegion::replaceRegisterInsideRegion(unsigned Register, 952*a06bfe05SJan Sjodin unsigned NewRegister, 953*a06bfe05SJan Sjodin bool IncludeLoopPHIs, 954*a06bfe05SJan Sjodin MachineRegisterInfo *MRI) { 955*a06bfe05SJan Sjodin replaceRegister(Register, NewRegister, MRI, true, false, IncludeLoopPHIs); 956*a06bfe05SJan Sjodin } 957*a06bfe05SJan Sjodin 958*a06bfe05SJan Sjodin void LinearizedRegion::replaceRegisterOutsideRegion(unsigned Register, 959*a06bfe05SJan Sjodin unsigned NewRegister, 960*a06bfe05SJan Sjodin bool IncludeLoopPHIs, 961*a06bfe05SJan Sjodin MachineRegisterInfo *MRI) { 962*a06bfe05SJan Sjodin replaceRegister(Register, NewRegister, MRI, false, true, IncludeLoopPHIs); 963*a06bfe05SJan Sjodin } 964*a06bfe05SJan Sjodin 965*a06bfe05SJan Sjodin DenseSet<unsigned> *LinearizedRegion::getLiveOuts() { return &LiveOuts; } 966*a06bfe05SJan Sjodin 967*a06bfe05SJan Sjodin void LinearizedRegion::setEntry(MachineBasicBlock *NewEntry) { 968*a06bfe05SJan Sjodin Entry = NewEntry; 969*a06bfe05SJan Sjodin } 970*a06bfe05SJan Sjodin 971*a06bfe05SJan Sjodin MachineBasicBlock *LinearizedRegion::getEntry() { return Entry; } 972*a06bfe05SJan Sjodin 973*a06bfe05SJan Sjodin void LinearizedRegion::setExit(MachineBasicBlock *NewExit) { Exit = NewExit; } 974*a06bfe05SJan Sjodin 975*a06bfe05SJan Sjodin MachineBasicBlock *LinearizedRegion::getExit() { return Exit; } 976*a06bfe05SJan Sjodin 977*a06bfe05SJan Sjodin void LinearizedRegion::addMBB(MachineBasicBlock *MBB) { MBBs.insert(MBB); } 978*a06bfe05SJan Sjodin 979*a06bfe05SJan Sjodin void LinearizedRegion::addMBBs(LinearizedRegion *InnerRegion) { 980*a06bfe05SJan Sjodin for (const auto &MBB : InnerRegion->MBBs) { 981*a06bfe05SJan Sjodin addMBB(MBB); 982*a06bfe05SJan Sjodin } 983*a06bfe05SJan Sjodin } 984*a06bfe05SJan Sjodin 985*a06bfe05SJan Sjodin bool LinearizedRegion::contains(MachineBasicBlock *MBB) { 986*a06bfe05SJan Sjodin return MBBs.count(MBB) == 1; 987*a06bfe05SJan Sjodin } 988*a06bfe05SJan Sjodin 989*a06bfe05SJan Sjodin bool LinearizedRegion::isLiveOut(unsigned Reg) { 990*a06bfe05SJan Sjodin return LiveOuts.count(Reg) == 1; 991*a06bfe05SJan Sjodin } 992*a06bfe05SJan Sjodin 993*a06bfe05SJan Sjodin bool LinearizedRegion::hasNoDef(unsigned Reg, MachineRegisterInfo *MRI) { 994*a06bfe05SJan Sjodin return MRI->def_begin(Reg) == MRI->def_end(); 995*a06bfe05SJan Sjodin } 996*a06bfe05SJan Sjodin 997*a06bfe05SJan Sjodin // After the code has been structurized, what was flagged as kills 998*a06bfe05SJan Sjodin // before are no longer register kills. 999*a06bfe05SJan Sjodin void LinearizedRegion::removeFalseRegisterKills(MachineRegisterInfo *MRI) { 1000*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); 1001*a06bfe05SJan Sjodin for (auto MBBI : MBBs) { 1002*a06bfe05SJan Sjodin MachineBasicBlock *MBB = MBBI; 1003*a06bfe05SJan Sjodin for (auto &II : *MBB) { 1004*a06bfe05SJan Sjodin for (auto &RI : II.uses()) { 1005*a06bfe05SJan Sjodin if (RI.isReg()) { 1006*a06bfe05SJan Sjodin unsigned Reg = RI.getReg(); 1007*a06bfe05SJan Sjodin if (TRI->isVirtualRegister(Reg)) { 1008*a06bfe05SJan Sjodin if (hasNoDef(Reg, MRI)) 1009*a06bfe05SJan Sjodin continue; 1010*a06bfe05SJan Sjodin if (!MRI->hasOneDef(Reg)) { 1011*a06bfe05SJan Sjodin DEBUG(this->getEntry()->getParent()->dump()); 1012*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(Reg, TRI) << "\n"); 1013*a06bfe05SJan Sjodin } 1014*a06bfe05SJan Sjodin 1015*a06bfe05SJan Sjodin if (MRI->def_begin(Reg) == MRI->def_end()) { 1016*a06bfe05SJan Sjodin DEBUG(dbgs() << "Register " 1017*a06bfe05SJan Sjodin << PrintReg(Reg, MRI->getTargetRegisterInfo()) 1018*a06bfe05SJan Sjodin << " has NO defs\n"); 1019*a06bfe05SJan Sjodin } else if (!MRI->hasOneDef(Reg)) { 1020*a06bfe05SJan Sjodin DEBUG(dbgs() << "Register " 1021*a06bfe05SJan Sjodin << PrintReg(Reg, MRI->getTargetRegisterInfo()) 1022*a06bfe05SJan Sjodin << " has multiple defs\n"); 1023*a06bfe05SJan Sjodin } 1024*a06bfe05SJan Sjodin 1025*a06bfe05SJan Sjodin assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 1026*a06bfe05SJan Sjodin MachineOperand *Def = &(*(MRI->def_begin(Reg))); 1027*a06bfe05SJan Sjodin MachineOperand *UseOperand = &(RI); 1028*a06bfe05SJan Sjodin bool UseIsOutsideDefMBB = Def->getParent()->getParent() != MBB; 1029*a06bfe05SJan Sjodin if (UseIsOutsideDefMBB && UseOperand->isKill()) { 1030*a06bfe05SJan Sjodin DEBUG(dbgs() << "Removing kill flag on register: " 1031*a06bfe05SJan Sjodin << PrintReg(Reg, TRI) << "\n"); 1032*a06bfe05SJan Sjodin UseOperand->setIsKill(false); 1033*a06bfe05SJan Sjodin } 1034*a06bfe05SJan Sjodin } 1035*a06bfe05SJan Sjodin } 1036*a06bfe05SJan Sjodin } 1037*a06bfe05SJan Sjodin } 1038*a06bfe05SJan Sjodin } 1039*a06bfe05SJan Sjodin } 1040*a06bfe05SJan Sjodin 1041*a06bfe05SJan Sjodin void LinearizedRegion::initLiveOut(RegionMRT *Region, 1042*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 1043*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 1044*a06bfe05SJan Sjodin PHILinearize &PHIInfo) { 1045*a06bfe05SJan Sjodin storeLiveOuts(Region, MRI, TRI, PHIInfo); 1046*a06bfe05SJan Sjodin } 1047*a06bfe05SJan Sjodin 1048*a06bfe05SJan Sjodin LinearizedRegion::LinearizedRegion(MachineBasicBlock *MBB, 1049*a06bfe05SJan Sjodin const MachineRegisterInfo *MRI, 1050*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI, 1051*a06bfe05SJan Sjodin PHILinearize &PHIInfo) { 1052*a06bfe05SJan Sjodin setEntry(MBB); 1053*a06bfe05SJan Sjodin setExit(MBB); 1054*a06bfe05SJan Sjodin storeLiveOuts(MBB, MRI, TRI, PHIInfo); 1055*a06bfe05SJan Sjodin MBBs.insert(MBB); 1056*a06bfe05SJan Sjodin Parent = nullptr; 1057*a06bfe05SJan Sjodin } 1058*a06bfe05SJan Sjodin 1059*a06bfe05SJan Sjodin LinearizedRegion::LinearizedRegion() { 1060*a06bfe05SJan Sjodin setEntry(nullptr); 1061*a06bfe05SJan Sjodin setExit(nullptr); 1062*a06bfe05SJan Sjodin Parent = nullptr; 1063*a06bfe05SJan Sjodin } 1064*a06bfe05SJan Sjodin 1065*a06bfe05SJan Sjodin LinearizedRegion::~LinearizedRegion() {} 1066*a06bfe05SJan Sjodin 1067*a06bfe05SJan Sjodin class AMDGPUMachineCFGStructurizer : public MachineFunctionPass { 1068*a06bfe05SJan Sjodin private: 1069*a06bfe05SJan Sjodin const MachineRegionInfo *Regions; 1070*a06bfe05SJan Sjodin const SIInstrInfo *TII; 1071*a06bfe05SJan Sjodin const TargetRegisterInfo *TRI; 1072*a06bfe05SJan Sjodin MachineRegisterInfo *MRI; 1073*a06bfe05SJan Sjodin unsigned BBSelectRegister; 1074*a06bfe05SJan Sjodin PHILinearize PHIInfo; 1075*a06bfe05SJan Sjodin DenseMap<MachineBasicBlock *, MachineBasicBlock *> FallthroughMap; 1076*a06bfe05SJan Sjodin 1077*a06bfe05SJan Sjodin void getPHIRegionIndices(RegionMRT *Region, MachineInstr &PHI, 1078*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &RegionIndices); 1079*a06bfe05SJan Sjodin void getPHIRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 1080*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &RegionIndices); 1081*a06bfe05SJan Sjodin void getPHINonRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 1082*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHINonRegionIndices); 1083*a06bfe05SJan Sjodin 1084*a06bfe05SJan Sjodin void storePHILinearizationInfoDest( 1085*a06bfe05SJan Sjodin unsigned LDestReg, MachineInstr &PHI, 1086*a06bfe05SJan Sjodin SmallVector<unsigned, 2> *RegionIndices = nullptr); 1087*a06bfe05SJan Sjodin 1088*a06bfe05SJan Sjodin unsigned storePHILinearizationInfo(MachineInstr &PHI, 1089*a06bfe05SJan Sjodin SmallVector<unsigned, 2> *RegionIndices); 1090*a06bfe05SJan Sjodin 1091*a06bfe05SJan Sjodin void extractKilledPHIs(MachineBasicBlock *MBB); 1092*a06bfe05SJan Sjodin 1093*a06bfe05SJan Sjodin bool shrinkPHI(MachineInstr &PHI, SmallVector<unsigned, 2> &PHIIndices, 1094*a06bfe05SJan Sjodin unsigned *ReplaceReg); 1095*a06bfe05SJan Sjodin 1096*a06bfe05SJan Sjodin bool shrinkPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 1097*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB, 1098*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIIndices, unsigned *ReplaceReg); 1099*a06bfe05SJan Sjodin 1100*a06bfe05SJan Sjodin void replacePHI(MachineInstr &PHI, unsigned CombinedSourceReg, 1101*a06bfe05SJan Sjodin MachineBasicBlock *LastMerge, 1102*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices); 1103*a06bfe05SJan Sjodin void replaceEntryPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 1104*a06bfe05SJan Sjodin MachineBasicBlock *IfMBB, 1105*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices); 1106*a06bfe05SJan Sjodin void replaceLiveOutRegs(MachineInstr &PHI, 1107*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices, 1108*a06bfe05SJan Sjodin unsigned CombinedSourceReg, 1109*a06bfe05SJan Sjodin LinearizedRegion *LRegion); 1110*a06bfe05SJan Sjodin void rewriteRegionExitPHI(RegionMRT *Region, MachineBasicBlock *LastMerge, 1111*a06bfe05SJan Sjodin MachineInstr &PHI, LinearizedRegion *LRegion); 1112*a06bfe05SJan Sjodin 1113*a06bfe05SJan Sjodin void rewriteRegionExitPHIs(RegionMRT *Region, MachineBasicBlock *LastMerge, 1114*a06bfe05SJan Sjodin LinearizedRegion *LRegion); 1115*a06bfe05SJan Sjodin void rewriteRegionEntryPHI(LinearizedRegion *Region, MachineBasicBlock *IfMBB, 1116*a06bfe05SJan Sjodin MachineInstr &PHI); 1117*a06bfe05SJan Sjodin void rewriteRegionEntryPHIs(LinearizedRegion *Region, 1118*a06bfe05SJan Sjodin MachineBasicBlock *IfMBB); 1119*a06bfe05SJan Sjodin 1120*a06bfe05SJan Sjodin bool regionIsSimpleIf(RegionMRT *Region); 1121*a06bfe05SJan Sjodin 1122*a06bfe05SJan Sjodin void transformSimpleIfRegion(RegionMRT *Region); 1123*a06bfe05SJan Sjodin 1124*a06bfe05SJan Sjodin void eliminateDeadBranchOperands(MachineBasicBlock::instr_iterator &II); 1125*a06bfe05SJan Sjodin 1126*a06bfe05SJan Sjodin void insertUnconditionalBranch(MachineBasicBlock *MBB, 1127*a06bfe05SJan Sjodin MachineBasicBlock *Dest, 1128*a06bfe05SJan Sjodin const DebugLoc &DL = DebugLoc()); 1129*a06bfe05SJan Sjodin 1130*a06bfe05SJan Sjodin MachineBasicBlock *createLinearizedExitBlock(RegionMRT *Region); 1131*a06bfe05SJan Sjodin 1132*a06bfe05SJan Sjodin void insertMergePHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 1133*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, unsigned DestRegister, 1134*a06bfe05SJan Sjodin unsigned IfSourceRegister, unsigned CodeSourceRegister, 1135*a06bfe05SJan Sjodin bool IsUndefIfSource = false); 1136*a06bfe05SJan Sjodin 1137*a06bfe05SJan Sjodin MachineBasicBlock *createIfBlock(MachineBasicBlock *MergeBB, 1138*a06bfe05SJan Sjodin MachineBasicBlock *CodeBBStart, 1139*a06bfe05SJan Sjodin MachineBasicBlock *CodeBBEnd, 1140*a06bfe05SJan Sjodin MachineBasicBlock *SelectBB, unsigned IfReg, 1141*a06bfe05SJan Sjodin bool InheritPreds); 1142*a06bfe05SJan Sjodin 1143*a06bfe05SJan Sjodin void prunePHIInfo(MachineBasicBlock *MBB); 1144*a06bfe05SJan Sjodin void createEntryPHI(LinearizedRegion *CurrentRegion, unsigned DestReg); 1145*a06bfe05SJan Sjodin 1146*a06bfe05SJan Sjodin void createEntryPHIs(LinearizedRegion *CurrentRegion); 1147*a06bfe05SJan Sjodin void resolvePHIInfos(MachineBasicBlock *FunctionEntry); 1148*a06bfe05SJan Sjodin 1149*a06bfe05SJan Sjodin void replaceRegisterWith(unsigned Register, unsigned NewRegister); 1150*a06bfe05SJan Sjodin 1151*a06bfe05SJan Sjodin MachineBasicBlock *createIfRegion(MachineBasicBlock *MergeBB, 1152*a06bfe05SJan Sjodin MachineBasicBlock *CodeBB, 1153*a06bfe05SJan Sjodin LinearizedRegion *LRegion, 1154*a06bfe05SJan Sjodin unsigned BBSelectRegIn, 1155*a06bfe05SJan Sjodin unsigned BBSelectRegOut); 1156*a06bfe05SJan Sjodin 1157*a06bfe05SJan Sjodin MachineBasicBlock * 1158*a06bfe05SJan Sjodin createIfRegion(MachineBasicBlock *MergeMBB, LinearizedRegion *InnerRegion, 1159*a06bfe05SJan Sjodin LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 1160*a06bfe05SJan Sjodin unsigned BBSelectRegIn, unsigned BBSelectRegOut); 1161*a06bfe05SJan Sjodin void ensureCondIsNotKilled(SmallVector<MachineOperand, 1> Cond); 1162*a06bfe05SJan Sjodin 1163*a06bfe05SJan Sjodin void rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 1164*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1165*a06bfe05SJan Sjodin unsigned BBSelectReg); 1166*a06bfe05SJan Sjodin 1167*a06bfe05SJan Sjodin MachineInstr *getDefInstr(unsigned Reg); 1168*a06bfe05SJan Sjodin void insertChainedPHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 1169*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1170*a06bfe05SJan Sjodin LinearizedRegion *InnerRegion, unsigned DestReg, 1171*a06bfe05SJan Sjodin unsigned SourceReg); 1172*a06bfe05SJan Sjodin bool containsDef(MachineBasicBlock *MBB, LinearizedRegion *InnerRegion, 1173*a06bfe05SJan Sjodin unsigned Register); 1174*a06bfe05SJan Sjodin void rewriteLiveOutRegs(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 1175*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1176*a06bfe05SJan Sjodin LinearizedRegion *InnerRegion, 1177*a06bfe05SJan Sjodin LinearizedRegion *LRegion); 1178*a06bfe05SJan Sjodin 1179*a06bfe05SJan Sjodin void splitLoopPHI(MachineInstr &PHI, MachineBasicBlock *Entry, 1180*a06bfe05SJan Sjodin MachineBasicBlock *EntrySucc, LinearizedRegion *LRegion); 1181*a06bfe05SJan Sjodin void splitLoopPHIs(MachineBasicBlock *Entry, MachineBasicBlock *EntrySucc, 1182*a06bfe05SJan Sjodin LinearizedRegion *LRegion); 1183*a06bfe05SJan Sjodin 1184*a06bfe05SJan Sjodin MachineBasicBlock *splitExit(LinearizedRegion *LRegion); 1185*a06bfe05SJan Sjodin 1186*a06bfe05SJan Sjodin MachineBasicBlock *splitEntry(LinearizedRegion *LRegion); 1187*a06bfe05SJan Sjodin 1188*a06bfe05SJan Sjodin LinearizedRegion *initLinearizedRegion(RegionMRT *Region); 1189*a06bfe05SJan Sjodin 1190*a06bfe05SJan Sjodin bool structurizeComplexRegion(RegionMRT *Region); 1191*a06bfe05SJan Sjodin 1192*a06bfe05SJan Sjodin bool structurizeRegion(RegionMRT *Region); 1193*a06bfe05SJan Sjodin 1194*a06bfe05SJan Sjodin bool structurizeRegions(RegionMRT *Region, bool isTopRegion); 1195*a06bfe05SJan Sjodin 1196*a06bfe05SJan Sjodin public: 1197*a06bfe05SJan Sjodin static char ID; 1198*a06bfe05SJan Sjodin 1199*a06bfe05SJan Sjodin void getAnalysisUsage(AnalysisUsage &AU) const override { 1200*a06bfe05SJan Sjodin AU.addRequired<MachineRegionInfoPass>(); 1201*a06bfe05SJan Sjodin MachineFunctionPass::getAnalysisUsage(AU); 1202*a06bfe05SJan Sjodin } 1203*a06bfe05SJan Sjodin 1204*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer() : MachineFunctionPass(ID) { 1205*a06bfe05SJan Sjodin initializeAMDGPUMachineCFGStructurizerPass(*PassRegistry::getPassRegistry()); 1206*a06bfe05SJan Sjodin } 1207*a06bfe05SJan Sjodin 1208*a06bfe05SJan Sjodin void initFallthroughMap(MachineFunction &MF); 1209*a06bfe05SJan Sjodin 1210*a06bfe05SJan Sjodin void createLinearizedRegion(RegionMRT *Region, unsigned SelectOut); 1211*a06bfe05SJan Sjodin 1212*a06bfe05SJan Sjodin unsigned initializeSelectRegisters(MRT *MRT, unsigned ExistingExitReg, 1213*a06bfe05SJan Sjodin MachineRegisterInfo *MRI, 1214*a06bfe05SJan Sjodin const SIInstrInfo *TII); 1215*a06bfe05SJan Sjodin 1216*a06bfe05SJan Sjodin RegionMRT *RMRT; 1217*a06bfe05SJan Sjodin void setRegionMRT(RegionMRT *RegionTree) { RMRT = RegionTree; } 1218*a06bfe05SJan Sjodin 1219*a06bfe05SJan Sjodin RegionMRT *getRegionMRT() { return RMRT; } 1220*a06bfe05SJan Sjodin 1221*a06bfe05SJan Sjodin bool runOnMachineFunction(MachineFunction &MF) override; 1222*a06bfe05SJan Sjodin }; 1223*a06bfe05SJan Sjodin } 1224*a06bfe05SJan Sjodin 1225*a06bfe05SJan Sjodin char AMDGPUMachineCFGStructurizer::ID = 0; 1226*a06bfe05SJan Sjodin 1227*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::regionIsSimpleIf(RegionMRT *Region) { 1228*a06bfe05SJan Sjodin MachineBasicBlock *Entry = Region->getEntry(); 1229*a06bfe05SJan Sjodin MachineBasicBlock *Succ = Region->getSucc(); 1230*a06bfe05SJan Sjodin bool FoundBypass = false; 1231*a06bfe05SJan Sjodin bool FoundIf = false; 1232*a06bfe05SJan Sjodin 1233*a06bfe05SJan Sjodin if (Entry->succ_size() != 2) { 1234*a06bfe05SJan Sjodin return false; 1235*a06bfe05SJan Sjodin } 1236*a06bfe05SJan Sjodin 1237*a06bfe05SJan Sjodin for (MachineBasicBlock::const_succ_iterator SI = Entry->succ_begin(), 1238*a06bfe05SJan Sjodin E = Entry->succ_end(); 1239*a06bfe05SJan Sjodin SI != E; ++SI) { 1240*a06bfe05SJan Sjodin MachineBasicBlock *Current = *SI; 1241*a06bfe05SJan Sjodin 1242*a06bfe05SJan Sjodin if (Current == Succ) { 1243*a06bfe05SJan Sjodin FoundBypass = true; 1244*a06bfe05SJan Sjodin } else if ((Current->succ_size() == 1) && 1245*a06bfe05SJan Sjodin *(Current->succ_begin()) == Succ) { 1246*a06bfe05SJan Sjodin FoundIf = true; 1247*a06bfe05SJan Sjodin } 1248*a06bfe05SJan Sjodin } 1249*a06bfe05SJan Sjodin 1250*a06bfe05SJan Sjodin return FoundIf && FoundBypass; 1251*a06bfe05SJan Sjodin } 1252*a06bfe05SJan Sjodin 1253*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::transformSimpleIfRegion(RegionMRT *Region) { 1254*a06bfe05SJan Sjodin MachineBasicBlock *Entry = Region->getEntry(); 1255*a06bfe05SJan Sjodin MachineBasicBlock *Exit = Region->getExit(); 1256*a06bfe05SJan Sjodin TII->convertNonUniformIfRegion(Entry, Exit); 1257*a06bfe05SJan Sjodin } 1258*a06bfe05SJan Sjodin 1259*a06bfe05SJan Sjodin static void fixMBBTerminator(MachineBasicBlock *MBB) { 1260*a06bfe05SJan Sjodin 1261*a06bfe05SJan Sjodin if (MBB->succ_size() == 1) { 1262*a06bfe05SJan Sjodin auto *Succ = *(MBB->succ_begin()); 1263*a06bfe05SJan Sjodin for (auto &TI : MBB->terminators()) { 1264*a06bfe05SJan Sjodin for (auto &UI : TI.uses()) { 1265*a06bfe05SJan Sjodin if (UI.isMBB() && UI.getMBB() != Succ) { 1266*a06bfe05SJan Sjodin UI.setMBB(Succ); 1267*a06bfe05SJan Sjodin } 1268*a06bfe05SJan Sjodin } 1269*a06bfe05SJan Sjodin } 1270*a06bfe05SJan Sjodin } 1271*a06bfe05SJan Sjodin } 1272*a06bfe05SJan Sjodin 1273*a06bfe05SJan Sjodin static void fixRegionTerminator(RegionMRT *Region) { 1274*a06bfe05SJan Sjodin MachineBasicBlock *InternalSucc = nullptr; 1275*a06bfe05SJan Sjodin MachineBasicBlock *ExternalSucc = nullptr; 1276*a06bfe05SJan Sjodin LinearizedRegion *LRegion = Region->getLinearizedRegion(); 1277*a06bfe05SJan Sjodin auto Exit = LRegion->getExit(); 1278*a06bfe05SJan Sjodin 1279*a06bfe05SJan Sjodin SmallPtrSet<MachineBasicBlock *, 2> Successors; 1280*a06bfe05SJan Sjodin for (MachineBasicBlock::const_succ_iterator SI = Exit->succ_begin(), 1281*a06bfe05SJan Sjodin SE = Exit->succ_end(); 1282*a06bfe05SJan Sjodin SI != SE; ++SI) { 1283*a06bfe05SJan Sjodin MachineBasicBlock *Succ = *SI; 1284*a06bfe05SJan Sjodin if (LRegion->contains(Succ)) { 1285*a06bfe05SJan Sjodin // Do not allow re-assign 1286*a06bfe05SJan Sjodin assert(InternalSucc == nullptr); 1287*a06bfe05SJan Sjodin InternalSucc = Succ; 1288*a06bfe05SJan Sjodin } else { 1289*a06bfe05SJan Sjodin // Do not allow re-assign 1290*a06bfe05SJan Sjodin assert(ExternalSucc == nullptr); 1291*a06bfe05SJan Sjodin ExternalSucc = Succ; 1292*a06bfe05SJan Sjodin } 1293*a06bfe05SJan Sjodin } 1294*a06bfe05SJan Sjodin 1295*a06bfe05SJan Sjodin for (auto &TI : Exit->terminators()) { 1296*a06bfe05SJan Sjodin for (auto &UI : TI.uses()) { 1297*a06bfe05SJan Sjodin if (UI.isMBB()) { 1298*a06bfe05SJan Sjodin auto Target = UI.getMBB(); 1299*a06bfe05SJan Sjodin if (Target != InternalSucc && Target != ExternalSucc) { 1300*a06bfe05SJan Sjodin UI.setMBB(ExternalSucc); 1301*a06bfe05SJan Sjodin } 1302*a06bfe05SJan Sjodin } 1303*a06bfe05SJan Sjodin } 1304*a06bfe05SJan Sjodin } 1305*a06bfe05SJan Sjodin } 1306*a06bfe05SJan Sjodin 1307*a06bfe05SJan Sjodin // If a region region is just a sequence of regions (and the exit 1308*a06bfe05SJan Sjodin // block in the case of the top level region), we can simply skip 1309*a06bfe05SJan Sjodin // linearizing it, because it is already linear 1310*a06bfe05SJan Sjodin bool regionIsSequence(RegionMRT *Region) { 1311*a06bfe05SJan Sjodin auto Children = Region->getChildren(); 1312*a06bfe05SJan Sjodin for (auto CI : *Children) { 1313*a06bfe05SJan Sjodin if (!CI->isRegion()) { 1314*a06bfe05SJan Sjodin if (CI->getMBBMRT()->getMBB()->succ_size() > 1) { 1315*a06bfe05SJan Sjodin return false; 1316*a06bfe05SJan Sjodin } 1317*a06bfe05SJan Sjodin } 1318*a06bfe05SJan Sjodin } 1319*a06bfe05SJan Sjodin return true; 1320*a06bfe05SJan Sjodin } 1321*a06bfe05SJan Sjodin 1322*a06bfe05SJan Sjodin void fixupRegionExits(RegionMRT *Region) { 1323*a06bfe05SJan Sjodin auto Children = Region->getChildren(); 1324*a06bfe05SJan Sjodin for (auto CI : *Children) { 1325*a06bfe05SJan Sjodin if (!CI->isRegion()) { 1326*a06bfe05SJan Sjodin fixMBBTerminator(CI->getMBBMRT()->getMBB()); 1327*a06bfe05SJan Sjodin } else { 1328*a06bfe05SJan Sjodin fixRegionTerminator(CI->getRegionMRT()); 1329*a06bfe05SJan Sjodin } 1330*a06bfe05SJan Sjodin } 1331*a06bfe05SJan Sjodin } 1332*a06bfe05SJan Sjodin 1333*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 1334*a06bfe05SJan Sjodin RegionMRT *Region, MachineInstr &PHI, 1335*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices) { 1336*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1337*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1338*a06bfe05SJan Sjodin MachineBasicBlock *Pred = getPHIPred(PHI, i); 1339*a06bfe05SJan Sjodin if (Region->contains(Pred)) { 1340*a06bfe05SJan Sjodin PHIRegionIndices.push_back(i); 1341*a06bfe05SJan Sjodin } 1342*a06bfe05SJan Sjodin } 1343*a06bfe05SJan Sjodin } 1344*a06bfe05SJan Sjodin 1345*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 1346*a06bfe05SJan Sjodin LinearizedRegion *Region, MachineInstr &PHI, 1347*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices) { 1348*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1349*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1350*a06bfe05SJan Sjodin MachineBasicBlock *Pred = getPHIPred(PHI, i); 1351*a06bfe05SJan Sjodin if (Region->contains(Pred)) { 1352*a06bfe05SJan Sjodin PHIRegionIndices.push_back(i); 1353*a06bfe05SJan Sjodin } 1354*a06bfe05SJan Sjodin } 1355*a06bfe05SJan Sjodin } 1356*a06bfe05SJan Sjodin 1357*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::getPHINonRegionIndices( 1358*a06bfe05SJan Sjodin LinearizedRegion *Region, MachineInstr &PHI, 1359*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHINonRegionIndices) { 1360*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1361*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1362*a06bfe05SJan Sjodin MachineBasicBlock *Pred = getPHIPred(PHI, i); 1363*a06bfe05SJan Sjodin if (!Region->contains(Pred)) { 1364*a06bfe05SJan Sjodin PHINonRegionIndices.push_back(i); 1365*a06bfe05SJan Sjodin } 1366*a06bfe05SJan Sjodin } 1367*a06bfe05SJan Sjodin } 1368*a06bfe05SJan Sjodin 1369*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::storePHILinearizationInfoDest( 1370*a06bfe05SJan Sjodin unsigned LDestReg, MachineInstr &PHI, 1371*a06bfe05SJan Sjodin SmallVector<unsigned, 2> *RegionIndices) { 1372*a06bfe05SJan Sjodin if (RegionIndices) { 1373*a06bfe05SJan Sjodin for (auto i : *RegionIndices) { 1374*a06bfe05SJan Sjodin PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 1375*a06bfe05SJan Sjodin } 1376*a06bfe05SJan Sjodin } else { 1377*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1378*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1379*a06bfe05SJan Sjodin PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 1380*a06bfe05SJan Sjodin } 1381*a06bfe05SJan Sjodin } 1382*a06bfe05SJan Sjodin } 1383*a06bfe05SJan Sjodin 1384*a06bfe05SJan Sjodin unsigned AMDGPUMachineCFGStructurizer::storePHILinearizationInfo( 1385*a06bfe05SJan Sjodin MachineInstr &PHI, SmallVector<unsigned, 2> *RegionIndices) { 1386*a06bfe05SJan Sjodin unsigned DestReg = getPHIDestReg(PHI); 1387*a06bfe05SJan Sjodin unsigned LinearizeDestReg = 1388*a06bfe05SJan Sjodin MRI->createVirtualRegister(MRI->getRegClass(DestReg)); 1389*a06bfe05SJan Sjodin PHIInfo.addDest(LinearizeDestReg, PHI.getDebugLoc()); 1390*a06bfe05SJan Sjodin storePHILinearizationInfoDest(LinearizeDestReg, PHI, RegionIndices); 1391*a06bfe05SJan Sjodin return LinearizeDestReg; 1392*a06bfe05SJan Sjodin } 1393*a06bfe05SJan Sjodin 1394*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::extractKilledPHIs(MachineBasicBlock *MBB) { 1395*a06bfe05SJan Sjodin // We need to create a new chain for the killed phi, but there is no 1396*a06bfe05SJan Sjodin // need to do the renaming outside or inside the block. 1397*a06bfe05SJan Sjodin SmallPtrSet<MachineInstr *, 2> PHIs; 1398*a06bfe05SJan Sjodin for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), 1399*a06bfe05SJan Sjodin E = MBB->instr_end(); 1400*a06bfe05SJan Sjodin I != E; ++I) { 1401*a06bfe05SJan Sjodin MachineInstr &Instr = *I; 1402*a06bfe05SJan Sjodin if (Instr.isPHI()) { 1403*a06bfe05SJan Sjodin unsigned PHIDestReg = getPHIDestReg(Instr); 1404*a06bfe05SJan Sjodin DEBUG(dbgs() << "Extractking killed phi:\n"); 1405*a06bfe05SJan Sjodin DEBUG(Instr.dump()); 1406*a06bfe05SJan Sjodin PHIs.insert(&Instr); 1407*a06bfe05SJan Sjodin PHIInfo.addDest(PHIDestReg, Instr.getDebugLoc()); 1408*a06bfe05SJan Sjodin storePHILinearizationInfoDest(PHIDestReg, Instr); 1409*a06bfe05SJan Sjodin } 1410*a06bfe05SJan Sjodin } 1411*a06bfe05SJan Sjodin 1412*a06bfe05SJan Sjodin for (auto PI : PHIs) { 1413*a06bfe05SJan Sjodin PI->eraseFromParent(); 1414*a06bfe05SJan Sjodin } 1415*a06bfe05SJan Sjodin } 1416*a06bfe05SJan Sjodin 1417*a06bfe05SJan Sjodin static bool isPHIRegionIndex(SmallVector<unsigned, 2> PHIRegionIndices, 1418*a06bfe05SJan Sjodin unsigned Index) { 1419*a06bfe05SJan Sjodin for (auto i : PHIRegionIndices) { 1420*a06bfe05SJan Sjodin if (i == Index) 1421*a06bfe05SJan Sjodin return true; 1422*a06bfe05SJan Sjodin } 1423*a06bfe05SJan Sjodin return false; 1424*a06bfe05SJan Sjodin } 1425*a06bfe05SJan Sjodin 1426*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 1427*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIIndices, 1428*a06bfe05SJan Sjodin unsigned *ReplaceReg) { 1429*a06bfe05SJan Sjodin return shrinkPHI(PHI, 0, nullptr, PHIIndices, ReplaceReg); 1430*a06bfe05SJan Sjodin } 1431*a06bfe05SJan Sjodin 1432*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 1433*a06bfe05SJan Sjodin unsigned CombinedSourceReg, 1434*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB, 1435*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIIndices, 1436*a06bfe05SJan Sjodin unsigned *ReplaceReg) { 1437*a06bfe05SJan Sjodin DEBUG(dbgs() << "Shrink PHI: "); 1438*a06bfe05SJan Sjodin DEBUG(PHI.dump()); 1439*a06bfe05SJan Sjodin DEBUG(dbgs() << " to " << PrintReg(getPHIDestReg(PHI), TRI) 1440*a06bfe05SJan Sjodin << "<def> = PHI("); 1441*a06bfe05SJan Sjodin 1442*a06bfe05SJan Sjodin bool Replaced = false; 1443*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1444*a06bfe05SJan Sjodin int SingleExternalEntryIndex = -1; 1445*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1446*a06bfe05SJan Sjodin if (!isPHIRegionIndex(PHIIndices, i)) { 1447*a06bfe05SJan Sjodin if (SingleExternalEntryIndex == -1) { 1448*a06bfe05SJan Sjodin // Single entry 1449*a06bfe05SJan Sjodin SingleExternalEntryIndex = i; 1450*a06bfe05SJan Sjodin } else { 1451*a06bfe05SJan Sjodin // Multiple entries 1452*a06bfe05SJan Sjodin SingleExternalEntryIndex = -2; 1453*a06bfe05SJan Sjodin } 1454*a06bfe05SJan Sjodin } 1455*a06bfe05SJan Sjodin } 1456*a06bfe05SJan Sjodin 1457*a06bfe05SJan Sjodin if (SingleExternalEntryIndex > -1) { 1458*a06bfe05SJan Sjodin *ReplaceReg = getPHISourceReg(PHI, SingleExternalEntryIndex); 1459*a06bfe05SJan Sjodin // We should not rewrite the code, we should only pick up the single value 1460*a06bfe05SJan Sjodin // that represents the shrunk PHI. 1461*a06bfe05SJan Sjodin Replaced = true; 1462*a06bfe05SJan Sjodin } else { 1463*a06bfe05SJan Sjodin MachineBasicBlock *MBB = PHI.getParent(); 1464*a06bfe05SJan Sjodin MachineInstrBuilder MIB = 1465*a06bfe05SJan Sjodin BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 1466*a06bfe05SJan Sjodin getPHIDestReg(PHI)); 1467*a06bfe05SJan Sjodin if (SourceMBB) { 1468*a06bfe05SJan Sjodin MIB.addReg(CombinedSourceReg); 1469*a06bfe05SJan Sjodin MIB.addMBB(SourceMBB); 1470*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(CombinedSourceReg, TRI) << ", BB#" 1471*a06bfe05SJan Sjodin << SourceMBB->getNumber()); 1472*a06bfe05SJan Sjodin } 1473*a06bfe05SJan Sjodin 1474*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1475*a06bfe05SJan Sjodin if (isPHIRegionIndex(PHIIndices, i)) { 1476*a06bfe05SJan Sjodin continue; 1477*a06bfe05SJan Sjodin } 1478*a06bfe05SJan Sjodin unsigned SourceReg = getPHISourceReg(PHI, i); 1479*a06bfe05SJan Sjodin MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 1480*a06bfe05SJan Sjodin MIB.addReg(SourceReg); 1481*a06bfe05SJan Sjodin MIB.addMBB(SourcePred); 1482*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(SourceReg, TRI) << ", BB#" 1483*a06bfe05SJan Sjodin << SourcePred->getNumber()); 1484*a06bfe05SJan Sjodin } 1485*a06bfe05SJan Sjodin DEBUG(dbgs() << ")\n"); 1486*a06bfe05SJan Sjodin } 1487*a06bfe05SJan Sjodin PHI.eraseFromParent(); 1488*a06bfe05SJan Sjodin return Replaced; 1489*a06bfe05SJan Sjodin } 1490*a06bfe05SJan Sjodin 1491*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::replacePHI( 1492*a06bfe05SJan Sjodin MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *LastMerge, 1493*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices) { 1494*a06bfe05SJan Sjodin DEBUG(dbgs() << "Replace PHI: "); 1495*a06bfe05SJan Sjodin DEBUG(PHI.dump()); 1496*a06bfe05SJan Sjodin DEBUG(dbgs() << " with " << PrintReg(getPHIDestReg(PHI), TRI) 1497*a06bfe05SJan Sjodin << "<def> = PHI("); 1498*a06bfe05SJan Sjodin 1499*a06bfe05SJan Sjodin bool HasExternalEdge = false; 1500*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1501*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1502*a06bfe05SJan Sjodin if (!isPHIRegionIndex(PHIRegionIndices, i)) { 1503*a06bfe05SJan Sjodin HasExternalEdge = true; 1504*a06bfe05SJan Sjodin } 1505*a06bfe05SJan Sjodin } 1506*a06bfe05SJan Sjodin 1507*a06bfe05SJan Sjodin if (HasExternalEdge) { 1508*a06bfe05SJan Sjodin MachineBasicBlock *MBB = PHI.getParent(); 1509*a06bfe05SJan Sjodin MachineInstrBuilder MIB = 1510*a06bfe05SJan Sjodin BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 1511*a06bfe05SJan Sjodin getPHIDestReg(PHI)); 1512*a06bfe05SJan Sjodin MIB.addReg(CombinedSourceReg); 1513*a06bfe05SJan Sjodin MIB.addMBB(LastMerge); 1514*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(CombinedSourceReg, TRI) << ", BB#" 1515*a06bfe05SJan Sjodin << LastMerge->getNumber()); 1516*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1517*a06bfe05SJan Sjodin if (isPHIRegionIndex(PHIRegionIndices, i)) { 1518*a06bfe05SJan Sjodin continue; 1519*a06bfe05SJan Sjodin } 1520*a06bfe05SJan Sjodin unsigned SourceReg = getPHISourceReg(PHI, i); 1521*a06bfe05SJan Sjodin MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 1522*a06bfe05SJan Sjodin MIB.addReg(SourceReg); 1523*a06bfe05SJan Sjodin MIB.addMBB(SourcePred); 1524*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(SourceReg, TRI) << ", BB#" 1525*a06bfe05SJan Sjodin << SourcePred->getNumber()); 1526*a06bfe05SJan Sjodin } 1527*a06bfe05SJan Sjodin DEBUG(dbgs() << ")\n"); 1528*a06bfe05SJan Sjodin } else { 1529*a06bfe05SJan Sjodin replaceRegisterWith(getPHIDestReg(PHI), CombinedSourceReg); 1530*a06bfe05SJan Sjodin } 1531*a06bfe05SJan Sjodin PHI.eraseFromParent(); 1532*a06bfe05SJan Sjodin } 1533*a06bfe05SJan Sjodin 1534*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::replaceEntryPHI( 1535*a06bfe05SJan Sjodin MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *IfMBB, 1536*a06bfe05SJan Sjodin SmallVector<unsigned, 2> &PHIRegionIndices) { 1537*a06bfe05SJan Sjodin 1538*a06bfe05SJan Sjodin DEBUG(dbgs() << "Replace entry PHI: "); 1539*a06bfe05SJan Sjodin DEBUG(PHI.dump()); 1540*a06bfe05SJan Sjodin DEBUG(dbgs() << " with "); 1541*a06bfe05SJan Sjodin 1542*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1543*a06bfe05SJan Sjodin unsigned NumNonRegionInputs = NumInputs; 1544*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1545*a06bfe05SJan Sjodin if (isPHIRegionIndex(PHIRegionIndices, i)) { 1546*a06bfe05SJan Sjodin NumNonRegionInputs--; 1547*a06bfe05SJan Sjodin } 1548*a06bfe05SJan Sjodin } 1549*a06bfe05SJan Sjodin 1550*a06bfe05SJan Sjodin if (NumNonRegionInputs == 0) { 1551*a06bfe05SJan Sjodin auto DestReg = getPHIDestReg(PHI); 1552*a06bfe05SJan Sjodin replaceRegisterWith(DestReg, CombinedSourceReg); 1553*a06bfe05SJan Sjodin DEBUG(dbgs() << " register " << PrintReg(CombinedSourceReg, TRI) << "\n"); 1554*a06bfe05SJan Sjodin PHI.eraseFromParent(); 1555*a06bfe05SJan Sjodin } else { 1556*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(getPHIDestReg(PHI), TRI) << "<def> = PHI("); 1557*a06bfe05SJan Sjodin MachineBasicBlock *MBB = PHI.getParent(); 1558*a06bfe05SJan Sjodin MachineInstrBuilder MIB = 1559*a06bfe05SJan Sjodin BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 1560*a06bfe05SJan Sjodin getPHIDestReg(PHI)); 1561*a06bfe05SJan Sjodin MIB.addReg(CombinedSourceReg); 1562*a06bfe05SJan Sjodin MIB.addMBB(IfMBB); 1563*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(CombinedSourceReg, TRI) << ", BB#" 1564*a06bfe05SJan Sjodin << IfMBB->getNumber()); 1565*a06bfe05SJan Sjodin unsigned NumInputs = getPHINumInputs(PHI); 1566*a06bfe05SJan Sjodin for (unsigned i = 0; i < NumInputs; ++i) { 1567*a06bfe05SJan Sjodin if (isPHIRegionIndex(PHIRegionIndices, i)) { 1568*a06bfe05SJan Sjodin continue; 1569*a06bfe05SJan Sjodin } 1570*a06bfe05SJan Sjodin unsigned SourceReg = getPHISourceReg(PHI, i); 1571*a06bfe05SJan Sjodin MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 1572*a06bfe05SJan Sjodin MIB.addReg(SourceReg); 1573*a06bfe05SJan Sjodin MIB.addMBB(SourcePred); 1574*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(SourceReg, TRI) << ", BB#" 1575*a06bfe05SJan Sjodin << SourcePred->getNumber()); 1576*a06bfe05SJan Sjodin } 1577*a06bfe05SJan Sjodin DEBUG(dbgs() << ")\n"); 1578*a06bfe05SJan Sjodin PHI.eraseFromParent(); 1579*a06bfe05SJan Sjodin } 1580*a06bfe05SJan Sjodin } 1581*a06bfe05SJan Sjodin 1582*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::replaceLiveOutRegs( 1583*a06bfe05SJan Sjodin MachineInstr &PHI, SmallVector<unsigned, 2> &PHIRegionIndices, 1584*a06bfe05SJan Sjodin unsigned CombinedSourceReg, LinearizedRegion *LRegion) { 1585*a06bfe05SJan Sjodin bool WasLiveOut = false; 1586*a06bfe05SJan Sjodin for (auto PII : PHIRegionIndices) { 1587*a06bfe05SJan Sjodin unsigned Reg = getPHISourceReg(PHI, PII); 1588*a06bfe05SJan Sjodin if (LRegion->isLiveOut(Reg)) { 1589*a06bfe05SJan Sjodin bool IsDead = true; 1590*a06bfe05SJan Sjodin 1591*a06bfe05SJan Sjodin // Check if register is live out of the basic block 1592*a06bfe05SJan Sjodin MachineBasicBlock *DefMBB = getDefInstr(Reg)->getParent(); 1593*a06bfe05SJan Sjodin for (auto UI = MRI->use_begin(Reg), E = MRI->use_end(); UI != E; ++UI) { 1594*a06bfe05SJan Sjodin if ((*UI).getParent()->getParent() != DefMBB) { 1595*a06bfe05SJan Sjodin IsDead = false; 1596*a06bfe05SJan Sjodin } 1597*a06bfe05SJan Sjodin } 1598*a06bfe05SJan Sjodin 1599*a06bfe05SJan Sjodin DEBUG(dbgs() << "Register " << PrintReg(Reg, TRI) << " is " 1600*a06bfe05SJan Sjodin << (IsDead ? "dead" : "alive") << " after PHI replace\n"); 1601*a06bfe05SJan Sjodin if (IsDead) { 1602*a06bfe05SJan Sjodin LRegion->removeLiveOut(Reg); 1603*a06bfe05SJan Sjodin } 1604*a06bfe05SJan Sjodin WasLiveOut = true; 1605*a06bfe05SJan Sjodin } 1606*a06bfe05SJan Sjodin } 1607*a06bfe05SJan Sjodin 1608*a06bfe05SJan Sjodin if (WasLiveOut) 1609*a06bfe05SJan Sjodin LRegion->addLiveOut(CombinedSourceReg); 1610*a06bfe05SJan Sjodin } 1611*a06bfe05SJan Sjodin 1612*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHI(RegionMRT *Region, 1613*a06bfe05SJan Sjodin MachineBasicBlock *LastMerge, 1614*a06bfe05SJan Sjodin MachineInstr &PHI, 1615*a06bfe05SJan Sjodin LinearizedRegion *LRegion) { 1616*a06bfe05SJan Sjodin SmallVector<unsigned, 2> PHIRegionIndices; 1617*a06bfe05SJan Sjodin getPHIRegionIndices(Region, PHI, PHIRegionIndices); 1618*a06bfe05SJan Sjodin unsigned LinearizedSourceReg = 1619*a06bfe05SJan Sjodin storePHILinearizationInfo(PHI, &PHIRegionIndices); 1620*a06bfe05SJan Sjodin 1621*a06bfe05SJan Sjodin replacePHI(PHI, LinearizedSourceReg, LastMerge, PHIRegionIndices); 1622*a06bfe05SJan Sjodin replaceLiveOutRegs(PHI, PHIRegionIndices, LinearizedSourceReg, LRegion); 1623*a06bfe05SJan Sjodin } 1624*a06bfe05SJan Sjodin 1625*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHI(LinearizedRegion *Region, 1626*a06bfe05SJan Sjodin MachineBasicBlock *IfMBB, 1627*a06bfe05SJan Sjodin MachineInstr &PHI) { 1628*a06bfe05SJan Sjodin SmallVector<unsigned, 2> PHINonRegionIndices; 1629*a06bfe05SJan Sjodin getPHINonRegionIndices(Region, PHI, PHINonRegionIndices); 1630*a06bfe05SJan Sjodin unsigned LinearizedSourceReg = 1631*a06bfe05SJan Sjodin storePHILinearizationInfo(PHI, &PHINonRegionIndices); 1632*a06bfe05SJan Sjodin replaceEntryPHI(PHI, LinearizedSourceReg, IfMBB, PHINonRegionIndices); 1633*a06bfe05SJan Sjodin } 1634*a06bfe05SJan Sjodin 1635*a06bfe05SJan Sjodin static void collectPHIs(MachineBasicBlock *MBB, 1636*a06bfe05SJan Sjodin SmallVector<MachineInstr *, 2> &PHIs) { 1637*a06bfe05SJan Sjodin for (auto &BBI : *MBB) { 1638*a06bfe05SJan Sjodin if (BBI.isPHI()) { 1639*a06bfe05SJan Sjodin PHIs.push_back(&BBI); 1640*a06bfe05SJan Sjodin } 1641*a06bfe05SJan Sjodin } 1642*a06bfe05SJan Sjodin } 1643*a06bfe05SJan Sjodin 1644*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHIs(RegionMRT *Region, 1645*a06bfe05SJan Sjodin MachineBasicBlock *LastMerge, 1646*a06bfe05SJan Sjodin LinearizedRegion *LRegion) { 1647*a06bfe05SJan Sjodin SmallVector<MachineInstr *, 2> PHIs; 1648*a06bfe05SJan Sjodin auto Exit = Region->getSucc(); 1649*a06bfe05SJan Sjodin if (Exit == nullptr) 1650*a06bfe05SJan Sjodin return; 1651*a06bfe05SJan Sjodin 1652*a06bfe05SJan Sjodin collectPHIs(Exit, PHIs); 1653*a06bfe05SJan Sjodin 1654*a06bfe05SJan Sjodin for (auto PHII : PHIs) { 1655*a06bfe05SJan Sjodin rewriteRegionExitPHI(Region, LastMerge, *PHII, LRegion); 1656*a06bfe05SJan Sjodin } 1657*a06bfe05SJan Sjodin } 1658*a06bfe05SJan Sjodin 1659*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHIs(LinearizedRegion *Region, 1660*a06bfe05SJan Sjodin MachineBasicBlock *IfMBB) { 1661*a06bfe05SJan Sjodin SmallVector<MachineInstr *, 2> PHIs; 1662*a06bfe05SJan Sjodin auto Entry = Region->getEntry(); 1663*a06bfe05SJan Sjodin 1664*a06bfe05SJan Sjodin collectPHIs(Entry, PHIs); 1665*a06bfe05SJan Sjodin 1666*a06bfe05SJan Sjodin for (auto PHII : PHIs) { 1667*a06bfe05SJan Sjodin rewriteRegionEntryPHI(Region, IfMBB, *PHII); 1668*a06bfe05SJan Sjodin } 1669*a06bfe05SJan Sjodin } 1670*a06bfe05SJan Sjodin 1671*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::insertUnconditionalBranch(MachineBasicBlock *MBB, 1672*a06bfe05SJan Sjodin MachineBasicBlock *Dest, 1673*a06bfe05SJan Sjodin const DebugLoc &DL) { 1674*a06bfe05SJan Sjodin DEBUG(dbgs() << "Inserting unconditional branch: " << MBB->getNumber() 1675*a06bfe05SJan Sjodin << " -> " << Dest->getNumber() << "\n"); 1676*a06bfe05SJan Sjodin MachineBasicBlock::instr_iterator Terminator = MBB->getFirstInstrTerminator(); 1677*a06bfe05SJan Sjodin bool HasTerminator = Terminator != MBB->instr_end(); 1678*a06bfe05SJan Sjodin if (HasTerminator) { 1679*a06bfe05SJan Sjodin TII->ReplaceTailWithBranchTo(Terminator, Dest); 1680*a06bfe05SJan Sjodin } 1681*a06bfe05SJan Sjodin if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(Dest)) { 1682*a06bfe05SJan Sjodin TII->insertUnconditionalBranch(*MBB, Dest, DL); 1683*a06bfe05SJan Sjodin } 1684*a06bfe05SJan Sjodin } 1685*a06bfe05SJan Sjodin 1686*a06bfe05SJan Sjodin static MachineBasicBlock *getSingleExitNode(MachineFunction &MF) { 1687*a06bfe05SJan Sjodin MachineBasicBlock *result = nullptr; 1688*a06bfe05SJan Sjodin for (auto &MFI : MF) { 1689*a06bfe05SJan Sjodin if (MFI.succ_size() == 0) { 1690*a06bfe05SJan Sjodin if (result == nullptr) { 1691*a06bfe05SJan Sjodin result = &MFI; 1692*a06bfe05SJan Sjodin } else { 1693*a06bfe05SJan Sjodin return nullptr; 1694*a06bfe05SJan Sjodin } 1695*a06bfe05SJan Sjodin } 1696*a06bfe05SJan Sjodin } 1697*a06bfe05SJan Sjodin 1698*a06bfe05SJan Sjodin return result; 1699*a06bfe05SJan Sjodin } 1700*a06bfe05SJan Sjodin 1701*a06bfe05SJan Sjodin static bool hasOneExitNode(MachineFunction &MF) { 1702*a06bfe05SJan Sjodin return getSingleExitNode(MF) != nullptr; 1703*a06bfe05SJan Sjodin } 1704*a06bfe05SJan Sjodin 1705*a06bfe05SJan Sjodin MachineBasicBlock * 1706*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer::createLinearizedExitBlock(RegionMRT *Region) { 1707*a06bfe05SJan Sjodin auto Exit = Region->getSucc(); 1708*a06bfe05SJan Sjodin 1709*a06bfe05SJan Sjodin // If the exit is the end of the function, we just use the existing 1710*a06bfe05SJan Sjodin MachineFunction *MF = Region->getEntry()->getParent(); 1711*a06bfe05SJan Sjodin if (Exit == nullptr && hasOneExitNode(*MF)) { 1712*a06bfe05SJan Sjodin return &(*(--(Region->getEntry()->getParent()->end()))); 1713*a06bfe05SJan Sjodin } 1714*a06bfe05SJan Sjodin 1715*a06bfe05SJan Sjodin MachineBasicBlock *LastMerge = MF->CreateMachineBasicBlock(); 1716*a06bfe05SJan Sjodin if (Exit == nullptr) { 1717*a06bfe05SJan Sjodin MachineFunction::iterator ExitIter = MF->end(); 1718*a06bfe05SJan Sjodin MF->insert(ExitIter, LastMerge); 1719*a06bfe05SJan Sjodin } else { 1720*a06bfe05SJan Sjodin MachineFunction::iterator ExitIter = Exit->getIterator(); 1721*a06bfe05SJan Sjodin MF->insert(ExitIter, LastMerge); 1722*a06bfe05SJan Sjodin LastMerge->addSuccessor(Exit); 1723*a06bfe05SJan Sjodin insertUnconditionalBranch(LastMerge, Exit); 1724*a06bfe05SJan Sjodin DEBUG(dbgs() << "Created exit block: " << LastMerge->getNumber() << "\n"); 1725*a06bfe05SJan Sjodin } 1726*a06bfe05SJan Sjodin return LastMerge; 1727*a06bfe05SJan Sjodin } 1728*a06bfe05SJan Sjodin 1729*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::insertMergePHI(MachineBasicBlock *IfBB, 1730*a06bfe05SJan Sjodin MachineBasicBlock *CodeBB, 1731*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1732*a06bfe05SJan Sjodin unsigned DestRegister, 1733*a06bfe05SJan Sjodin unsigned IfSourceRegister, 1734*a06bfe05SJan Sjodin unsigned CodeSourceRegister, 1735*a06bfe05SJan Sjodin bool IsUndefIfSource) { 1736*a06bfe05SJan Sjodin // If this is the function exit block, we don't need a phi. 1737*a06bfe05SJan Sjodin if (MergeBB->succ_begin() == MergeBB->succ_end()) { 1738*a06bfe05SJan Sjodin return; 1739*a06bfe05SJan Sjodin } 1740*a06bfe05SJan Sjodin DEBUG(dbgs() << "Merge PHI (BB#" << MergeBB->getNumber() 1741*a06bfe05SJan Sjodin << "): " << PrintReg(DestRegister, TRI) << "<def> = PHI(" 1742*a06bfe05SJan Sjodin << PrintReg(IfSourceRegister, TRI) << ", BB#" 1743*a06bfe05SJan Sjodin << IfBB->getNumber() << PrintReg(CodeSourceRegister, TRI) 1744*a06bfe05SJan Sjodin << ", BB#" << CodeBB->getNumber() << ")\n"); 1745*a06bfe05SJan Sjodin const DebugLoc &DL = MergeBB->findDebugLoc(MergeBB->begin()); 1746*a06bfe05SJan Sjodin MachineInstrBuilder MIB = BuildMI(*MergeBB, MergeBB->instr_begin(), DL, 1747*a06bfe05SJan Sjodin TII->get(TargetOpcode::PHI), DestRegister); 1748*a06bfe05SJan Sjodin if (IsUndefIfSource && false) { 1749*a06bfe05SJan Sjodin MIB.addReg(IfSourceRegister, RegState::Undef); 1750*a06bfe05SJan Sjodin } else { 1751*a06bfe05SJan Sjodin MIB.addReg(IfSourceRegister); 1752*a06bfe05SJan Sjodin } 1753*a06bfe05SJan Sjodin MIB.addMBB(IfBB); 1754*a06bfe05SJan Sjodin MIB.addReg(CodeSourceRegister); 1755*a06bfe05SJan Sjodin MIB.addMBB(CodeBB); 1756*a06bfe05SJan Sjodin } 1757*a06bfe05SJan Sjodin 1758*a06bfe05SJan Sjodin static void removeExternalCFGSuccessors(MachineBasicBlock *MBB) { 1759*a06bfe05SJan Sjodin for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(), 1760*a06bfe05SJan Sjodin E = MBB->succ_end(); 1761*a06bfe05SJan Sjodin PI != E; ++PI) { 1762*a06bfe05SJan Sjodin if ((*PI) != MBB) { 1763*a06bfe05SJan Sjodin (MBB)->removeSuccessor(*PI); 1764*a06bfe05SJan Sjodin } 1765*a06bfe05SJan Sjodin } 1766*a06bfe05SJan Sjodin } 1767*a06bfe05SJan Sjodin 1768*a06bfe05SJan Sjodin static void removeExternalCFGEdges(MachineBasicBlock *StartMBB, 1769*a06bfe05SJan Sjodin MachineBasicBlock *EndMBB) { 1770*a06bfe05SJan Sjodin 1771*a06bfe05SJan Sjodin // We have to check against the StartMBB successor becasuse a 1772*a06bfe05SJan Sjodin // structurized region with a loop will have the entry block split, 1773*a06bfe05SJan Sjodin // and the backedge will go to the entry successor. 1774*a06bfe05SJan Sjodin DenseSet<std::pair<MachineBasicBlock *, MachineBasicBlock *>> Succs; 1775*a06bfe05SJan Sjodin unsigned SuccSize = StartMBB->succ_size(); 1776*a06bfe05SJan Sjodin if (SuccSize > 0) { 1777*a06bfe05SJan Sjodin MachineBasicBlock *StartMBBSucc = *(StartMBB->succ_begin()); 1778*a06bfe05SJan Sjodin for (MachineBasicBlock::succ_iterator PI = EndMBB->succ_begin(), 1779*a06bfe05SJan Sjodin E = EndMBB->succ_end(); 1780*a06bfe05SJan Sjodin PI != E; ++PI) { 1781*a06bfe05SJan Sjodin // Either we have a back-edge to the entry block, or a back-edge to the 1782*a06bfe05SJan Sjodin // succesor of the entry block since the block may be split. 1783*a06bfe05SJan Sjodin if ((*PI) != StartMBB && 1784*a06bfe05SJan Sjodin !((*PI) == StartMBBSucc && StartMBB != EndMBB && SuccSize == 1)) { 1785*a06bfe05SJan Sjodin Succs.insert( 1786*a06bfe05SJan Sjodin std::pair<MachineBasicBlock *, MachineBasicBlock *>(EndMBB, *PI)); 1787*a06bfe05SJan Sjodin } 1788*a06bfe05SJan Sjodin } 1789*a06bfe05SJan Sjodin } 1790*a06bfe05SJan Sjodin 1791*a06bfe05SJan Sjodin for (MachineBasicBlock::pred_iterator PI = StartMBB->pred_begin(), 1792*a06bfe05SJan Sjodin E = StartMBB->pred_end(); 1793*a06bfe05SJan Sjodin PI != E; ++PI) { 1794*a06bfe05SJan Sjodin if ((*PI) != EndMBB) { 1795*a06bfe05SJan Sjodin Succs.insert( 1796*a06bfe05SJan Sjodin std::pair<MachineBasicBlock *, MachineBasicBlock *>(*PI, StartMBB)); 1797*a06bfe05SJan Sjodin } 1798*a06bfe05SJan Sjodin } 1799*a06bfe05SJan Sjodin 1800*a06bfe05SJan Sjodin for (auto SI : Succs) { 1801*a06bfe05SJan Sjodin std::pair<MachineBasicBlock *, MachineBasicBlock *> Edge = SI; 1802*a06bfe05SJan Sjodin DEBUG(dbgs() << "Removing edge: BB#" << Edge.first->getNumber() << " -> BB#" 1803*a06bfe05SJan Sjodin << Edge.second->getNumber() << "\n"); 1804*a06bfe05SJan Sjodin Edge.first->removeSuccessor(Edge.second); 1805*a06bfe05SJan Sjodin } 1806*a06bfe05SJan Sjodin } 1807*a06bfe05SJan Sjodin 1808*a06bfe05SJan Sjodin MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfBlock( 1809*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBBStart, 1810*a06bfe05SJan Sjodin MachineBasicBlock *CodeBBEnd, MachineBasicBlock *SelectBB, unsigned IfReg, 1811*a06bfe05SJan Sjodin bool InheritPreds) { 1812*a06bfe05SJan Sjodin MachineFunction *MF = MergeBB->getParent(); 1813*a06bfe05SJan Sjodin MachineBasicBlock *IfBB = MF->CreateMachineBasicBlock(); 1814*a06bfe05SJan Sjodin 1815*a06bfe05SJan Sjodin if (InheritPreds) { 1816*a06bfe05SJan Sjodin for (MachineBasicBlock::pred_iterator PI = CodeBBStart->pred_begin(), 1817*a06bfe05SJan Sjodin E = CodeBBStart->pred_end(); 1818*a06bfe05SJan Sjodin PI != E; ++PI) { 1819*a06bfe05SJan Sjodin if ((*PI) != CodeBBEnd) { 1820*a06bfe05SJan Sjodin MachineBasicBlock *Pred = (*PI); 1821*a06bfe05SJan Sjodin Pred->addSuccessor(IfBB); 1822*a06bfe05SJan Sjodin } 1823*a06bfe05SJan Sjodin } 1824*a06bfe05SJan Sjodin } 1825*a06bfe05SJan Sjodin 1826*a06bfe05SJan Sjodin removeExternalCFGEdges(CodeBBStart, CodeBBEnd); 1827*a06bfe05SJan Sjodin 1828*a06bfe05SJan Sjodin auto CodeBBStartI = CodeBBStart->getIterator(); 1829*a06bfe05SJan Sjodin auto CodeBBEndI = CodeBBEnd->getIterator(); 1830*a06bfe05SJan Sjodin auto MergeIter = MergeBB->getIterator(); 1831*a06bfe05SJan Sjodin MF->insert(MergeIter, IfBB); 1832*a06bfe05SJan Sjodin MF->splice(MergeIter, CodeBBStartI, ++CodeBBEndI); 1833*a06bfe05SJan Sjodin IfBB->addSuccessor(MergeBB); 1834*a06bfe05SJan Sjodin IfBB->addSuccessor(CodeBBStart); 1835*a06bfe05SJan Sjodin 1836*a06bfe05SJan Sjodin DEBUG(dbgs() << "Created If block: " << IfBB->getNumber() << "\n"); 1837*a06bfe05SJan Sjodin // Ensure that the MergeBB is a succesor of the CodeEndBB. 1838*a06bfe05SJan Sjodin if (!CodeBBEnd->isSuccessor(MergeBB)) 1839*a06bfe05SJan Sjodin CodeBBEnd->addSuccessor(MergeBB); 1840*a06bfe05SJan Sjodin 1841*a06bfe05SJan Sjodin DEBUG(dbgs() << "Moved MBB#" << CodeBBStart->getNumber() << " through MBB#" 1842*a06bfe05SJan Sjodin << CodeBBEnd->getNumber() << "\n"); 1843*a06bfe05SJan Sjodin 1844*a06bfe05SJan Sjodin // If we have a single predecessor we can find a reasonable debug location 1845*a06bfe05SJan Sjodin MachineBasicBlock *SinglePred = 1846*a06bfe05SJan Sjodin CodeBBStart->pred_size() == 1 ? *(CodeBBStart->pred_begin()) : nullptr; 1847*a06bfe05SJan Sjodin const DebugLoc &DL = SinglePred 1848*a06bfe05SJan Sjodin ? SinglePred->findDebugLoc(SinglePred->getFirstTerminator()) 1849*a06bfe05SJan Sjodin : DebugLoc(); 1850*a06bfe05SJan Sjodin 1851*a06bfe05SJan Sjodin unsigned Reg = 1852*a06bfe05SJan Sjodin TII->insertEQ(IfBB, IfBB->begin(), DL, IfReg, 1853*a06bfe05SJan Sjodin SelectBB->getNumber() /* CodeBBStart->getNumber() */); 1854*a06bfe05SJan Sjodin if (&(*(IfBB->getParent()->begin())) == IfBB) { 1855*a06bfe05SJan Sjodin TII->materializeImmediate(*IfBB, IfBB->begin(), DL, IfReg, 1856*a06bfe05SJan Sjodin CodeBBStart->getNumber()); 1857*a06bfe05SJan Sjodin } 1858*a06bfe05SJan Sjodin MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 1859*a06bfe05SJan Sjodin ArrayRef<MachineOperand> Cond(RegOp); 1860*a06bfe05SJan Sjodin TII->insertBranch(*IfBB, MergeBB, CodeBBStart, Cond, DL); 1861*a06bfe05SJan Sjodin 1862*a06bfe05SJan Sjodin return IfBB; 1863*a06bfe05SJan Sjodin } 1864*a06bfe05SJan Sjodin 1865*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::ensureCondIsNotKilled( 1866*a06bfe05SJan Sjodin SmallVector<MachineOperand, 1> Cond) { 1867*a06bfe05SJan Sjodin if (Cond.size() != 1) 1868*a06bfe05SJan Sjodin return; 1869*a06bfe05SJan Sjodin if (!Cond[0].isReg()) 1870*a06bfe05SJan Sjodin return; 1871*a06bfe05SJan Sjodin 1872*a06bfe05SJan Sjodin unsigned CondReg = Cond[0].getReg(); 1873*a06bfe05SJan Sjodin for (auto UI = MRI->use_begin(CondReg), E = MRI->use_end(); UI != E; ++UI) { 1874*a06bfe05SJan Sjodin (*UI).setIsKill(false); 1875*a06bfe05SJan Sjodin } 1876*a06bfe05SJan Sjodin } 1877*a06bfe05SJan Sjodin 1878*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 1879*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1880*a06bfe05SJan Sjodin unsigned BBSelectReg) { 1881*a06bfe05SJan Sjodin MachineBasicBlock *TrueBB = nullptr; 1882*a06bfe05SJan Sjodin MachineBasicBlock *FalseBB = nullptr; 1883*a06bfe05SJan Sjodin SmallVector<MachineOperand, 1> Cond; 1884*a06bfe05SJan Sjodin MachineBasicBlock *FallthroughBB = FallthroughMap[CodeBB]; 1885*a06bfe05SJan Sjodin TII->analyzeBranch(*CodeBB, TrueBB, FalseBB, Cond); 1886*a06bfe05SJan Sjodin 1887*a06bfe05SJan Sjodin const DebugLoc &DL = CodeBB->findDebugLoc(CodeBB->getFirstTerminator()); 1888*a06bfe05SJan Sjodin 1889*a06bfe05SJan Sjodin if (FalseBB == nullptr && TrueBB == nullptr && FallthroughBB == nullptr) { 1890*a06bfe05SJan Sjodin // This is an exit block, hence no successors. We will assign the 1891*a06bfe05SJan Sjodin // bb select register to the entry block. 1892*a06bfe05SJan Sjodin TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 1893*a06bfe05SJan Sjodin BBSelectReg, 1894*a06bfe05SJan Sjodin CodeBB->getParent()->begin()->getNumber()); 1895*a06bfe05SJan Sjodin insertUnconditionalBranch(CodeBB, MergeBB, DL); 1896*a06bfe05SJan Sjodin return; 1897*a06bfe05SJan Sjodin } 1898*a06bfe05SJan Sjodin 1899*a06bfe05SJan Sjodin if (FalseBB == nullptr && TrueBB == nullptr) { 1900*a06bfe05SJan Sjodin TrueBB = FallthroughBB; 1901*a06bfe05SJan Sjodin } else if (TrueBB != nullptr) { 1902*a06bfe05SJan Sjodin FalseBB = 1903*a06bfe05SJan Sjodin (FallthroughBB && (FallthroughBB != TrueBB)) ? FallthroughBB : FalseBB; 1904*a06bfe05SJan Sjodin } 1905*a06bfe05SJan Sjodin 1906*a06bfe05SJan Sjodin if ((TrueBB != nullptr && FalseBB == nullptr) || (TrueBB == FalseBB)) { 1907*a06bfe05SJan Sjodin TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 1908*a06bfe05SJan Sjodin BBSelectReg, TrueBB->getNumber()); 1909*a06bfe05SJan Sjodin } else { 1910*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectReg); 1911*a06bfe05SJan Sjodin unsigned TrueBBReg = MRI->createVirtualRegister(RegClass); 1912*a06bfe05SJan Sjodin unsigned FalseBBReg = MRI->createVirtualRegister(RegClass); 1913*a06bfe05SJan Sjodin TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 1914*a06bfe05SJan Sjodin TrueBBReg, TrueBB->getNumber()); 1915*a06bfe05SJan Sjodin TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 1916*a06bfe05SJan Sjodin FalseBBReg, FalseBB->getNumber()); 1917*a06bfe05SJan Sjodin ensureCondIsNotKilled(Cond); 1918*a06bfe05SJan Sjodin TII->insertVectorSelect(*CodeBB, CodeBB->getFirstTerminator(), DL, 1919*a06bfe05SJan Sjodin BBSelectReg, Cond, TrueBBReg, FalseBBReg); 1920*a06bfe05SJan Sjodin } 1921*a06bfe05SJan Sjodin 1922*a06bfe05SJan Sjodin insertUnconditionalBranch(CodeBB, MergeBB, DL); 1923*a06bfe05SJan Sjodin } 1924*a06bfe05SJan Sjodin 1925*a06bfe05SJan Sjodin MachineInstr *AMDGPUMachineCFGStructurizer::getDefInstr(unsigned Reg) { 1926*a06bfe05SJan Sjodin if (MRI->def_begin(Reg) == MRI->def_end()) { 1927*a06bfe05SJan Sjodin DEBUG(dbgs() << "Register " << PrintReg(Reg, MRI->getTargetRegisterInfo()) 1928*a06bfe05SJan Sjodin << " has NO defs\n"); 1929*a06bfe05SJan Sjodin } else if (!MRI->hasOneDef(Reg)) { 1930*a06bfe05SJan Sjodin DEBUG(dbgs() << "Register " << PrintReg(Reg, MRI->getTargetRegisterInfo()) 1931*a06bfe05SJan Sjodin << " has multiple defs\n"); 1932*a06bfe05SJan Sjodin DEBUG(dbgs() << "DEFS BEGIN:\n"); 1933*a06bfe05SJan Sjodin for (auto DI = MRI->def_begin(Reg), DE = MRI->def_end(); DI != DE; ++DI) { 1934*a06bfe05SJan Sjodin DEBUG(DI->getParent()->dump()); 1935*a06bfe05SJan Sjodin } 1936*a06bfe05SJan Sjodin DEBUG(dbgs() << "DEFS END\n"); 1937*a06bfe05SJan Sjodin } 1938*a06bfe05SJan Sjodin 1939*a06bfe05SJan Sjodin assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 1940*a06bfe05SJan Sjodin return (*(MRI->def_begin(Reg))).getParent(); 1941*a06bfe05SJan Sjodin } 1942*a06bfe05SJan Sjodin 1943*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::insertChainedPHI(MachineBasicBlock *IfBB, 1944*a06bfe05SJan Sjodin MachineBasicBlock *CodeBB, 1945*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 1946*a06bfe05SJan Sjodin LinearizedRegion *InnerRegion, 1947*a06bfe05SJan Sjodin unsigned DestReg, 1948*a06bfe05SJan Sjodin unsigned SourceReg) { 1949*a06bfe05SJan Sjodin // In this function we know we are part of a chain already, so we need 1950*a06bfe05SJan Sjodin // to add the registers to the existing chain, and rename the register 1951*a06bfe05SJan Sjodin // inside the region. 1952*a06bfe05SJan Sjodin bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 1953*a06bfe05SJan Sjodin MachineInstr *DefInstr = getDefInstr(SourceReg); 1954*a06bfe05SJan Sjodin if (DefInstr->isPHI() && DefInstr->getParent() == CodeBB && IsSingleBB) { 1955*a06bfe05SJan Sjodin // Handle the case where the def is a PHI-def inside a basic 1956*a06bfe05SJan Sjodin // block, then we only need to do renaming. Special care needs to 1957*a06bfe05SJan Sjodin // be taken if the PHI-def is part of an existing chain, or if a 1958*a06bfe05SJan Sjodin // new one needs to be created. 1959*a06bfe05SJan Sjodin InnerRegion->replaceRegisterInsideRegion(SourceReg, DestReg, true, MRI); 1960*a06bfe05SJan Sjodin 1961*a06bfe05SJan Sjodin // We collect all PHI Information, and if we are at the region entry, 1962*a06bfe05SJan Sjodin // all PHIs will be removed, and then re-introduced if needed. 1963*a06bfe05SJan Sjodin storePHILinearizationInfoDest(DestReg, *DefInstr); 1964*a06bfe05SJan Sjodin // We have picked up all the information we need now and can remove 1965*a06bfe05SJan Sjodin // the PHI 1966*a06bfe05SJan Sjodin PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 1967*a06bfe05SJan Sjodin DefInstr->eraseFromParent(); 1968*a06bfe05SJan Sjodin } else { 1969*a06bfe05SJan Sjodin // If this is not a phi-def, or it is a phi-def but from a linearized region 1970*a06bfe05SJan Sjodin if (IsSingleBB && DefInstr->getParent() == InnerRegion->getEntry()) { 1971*a06bfe05SJan Sjodin // If this is a single BB and the definition is in this block we 1972*a06bfe05SJan Sjodin // need to replace any uses outside the region. 1973*a06bfe05SJan Sjodin InnerRegion->replaceRegisterOutsideRegion(SourceReg, DestReg, false, MRI); 1974*a06bfe05SJan Sjodin } 1975*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = MRI->getRegClass(DestReg); 1976*a06bfe05SJan Sjodin unsigned NextDestReg = MRI->createVirtualRegister(RegClass); 1977*a06bfe05SJan Sjodin bool IsLastDef = PHIInfo.getNumSources(DestReg) == 1; 1978*a06bfe05SJan Sjodin DEBUG(dbgs() << "Insert Chained PHI\n"); 1979*a06bfe05SJan Sjodin insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, DestReg, NextDestReg, 1980*a06bfe05SJan Sjodin SourceReg, IsLastDef); 1981*a06bfe05SJan Sjodin 1982*a06bfe05SJan Sjodin PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 1983*a06bfe05SJan Sjodin if (IsLastDef) { 1984*a06bfe05SJan Sjodin const DebugLoc &DL = IfBB->findDebugLoc(IfBB->getFirstTerminator()); 1985*a06bfe05SJan Sjodin TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DL, 1986*a06bfe05SJan Sjodin NextDestReg, 0); 1987*a06bfe05SJan Sjodin PHIInfo.deleteDef(DestReg); 1988*a06bfe05SJan Sjodin } else { 1989*a06bfe05SJan Sjodin PHIInfo.replaceDef(DestReg, NextDestReg); 1990*a06bfe05SJan Sjodin } 1991*a06bfe05SJan Sjodin } 1992*a06bfe05SJan Sjodin } 1993*a06bfe05SJan Sjodin 1994*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::containsDef(MachineBasicBlock *MBB, 1995*a06bfe05SJan Sjodin LinearizedRegion *InnerRegion, 1996*a06bfe05SJan Sjodin unsigned Register) { 1997*a06bfe05SJan Sjodin return getDefInstr(Register)->getParent() == MBB || 1998*a06bfe05SJan Sjodin InnerRegion->contains(getDefInstr(Register)->getParent()); 1999*a06bfe05SJan Sjodin } 2000*a06bfe05SJan Sjodin 2001*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::rewriteLiveOutRegs(MachineBasicBlock *IfBB, 2002*a06bfe05SJan Sjodin MachineBasicBlock *CodeBB, 2003*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, 2004*a06bfe05SJan Sjodin LinearizedRegion *InnerRegion, 2005*a06bfe05SJan Sjodin LinearizedRegion *LRegion) { 2006*a06bfe05SJan Sjodin DenseSet<unsigned> *LiveOuts = InnerRegion->getLiveOuts(); 2007*a06bfe05SJan Sjodin SmallVector<unsigned, 4> OldLiveOuts; 2008*a06bfe05SJan Sjodin bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 2009*a06bfe05SJan Sjodin for (auto OLI : *LiveOuts) { 2010*a06bfe05SJan Sjodin OldLiveOuts.push_back(OLI); 2011*a06bfe05SJan Sjodin } 2012*a06bfe05SJan Sjodin 2013*a06bfe05SJan Sjodin for (auto LI : OldLiveOuts) { 2014*a06bfe05SJan Sjodin DEBUG(dbgs() << "LiveOut: " << PrintReg(LI, TRI)); 2015*a06bfe05SJan Sjodin if (!containsDef(CodeBB, InnerRegion, LI) || 2016*a06bfe05SJan Sjodin (!IsSingleBB && (getDefInstr(LI)->getParent() == LRegion->getExit()))) { 2017*a06bfe05SJan Sjodin // If the register simly lives through the CodeBB, we don't have 2018*a06bfe05SJan Sjodin // to rewrite anything since the register is not defined in this 2019*a06bfe05SJan Sjodin // part of the code. 2020*a06bfe05SJan Sjodin DEBUG(dbgs() << "- through"); 2021*a06bfe05SJan Sjodin continue; 2022*a06bfe05SJan Sjodin } 2023*a06bfe05SJan Sjodin DEBUG(dbgs() << "\n"); 2024*a06bfe05SJan Sjodin unsigned Reg = LI; 2025*a06bfe05SJan Sjodin if (/*!PHIInfo.isSource(Reg) &&*/ Reg != InnerRegion->getBBSelectRegOut()) { 2026*a06bfe05SJan Sjodin // If the register is live out, we do want to create a phi, 2027*a06bfe05SJan Sjodin // unless it is from the Exit block, becasuse in that case there 2028*a06bfe05SJan Sjodin // is already a PHI, and no need to create a new one. 2029*a06bfe05SJan Sjodin 2030*a06bfe05SJan Sjodin // If the register is just a live out def and not part of a phi 2031*a06bfe05SJan Sjodin // chain, we need to create a PHI node to handle the if region, 2032*a06bfe05SJan Sjodin // and replace all uses outside of the region with the new dest 2033*a06bfe05SJan Sjodin // register, unless it is the outgoing BB select register. We have 2034*a06bfe05SJan Sjodin // already creaed phi nodes for these. 2035*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = MRI->getRegClass(Reg); 2036*a06bfe05SJan Sjodin unsigned PHIDestReg = MRI->createVirtualRegister(RegClass); 2037*a06bfe05SJan Sjodin unsigned IfSourceReg = MRI->createVirtualRegister(RegClass); 2038*a06bfe05SJan Sjodin // Create initializer, this value is never used, but is needed 2039*a06bfe05SJan Sjodin // to satisfy SSA. 2040*a06bfe05SJan Sjodin DEBUG(dbgs() << "Initializer for reg: " << PrintReg(Reg) << "\n"); 2041*a06bfe05SJan Sjodin TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DebugLoc(), 2042*a06bfe05SJan Sjodin IfSourceReg, 0); 2043*a06bfe05SJan Sjodin 2044*a06bfe05SJan Sjodin InnerRegion->replaceRegisterOutsideRegion(Reg, PHIDestReg, true, MRI); 2045*a06bfe05SJan Sjodin DEBUG(dbgs() << "Insert Non-Chained Live out PHI\n"); 2046*a06bfe05SJan Sjodin insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, PHIDestReg, 2047*a06bfe05SJan Sjodin IfSourceReg, Reg, true); 2048*a06bfe05SJan Sjodin } 2049*a06bfe05SJan Sjodin } 2050*a06bfe05SJan Sjodin 2051*a06bfe05SJan Sjodin // Handle the chained definitions in PHIInfo, checking if this basic block 2052*a06bfe05SJan Sjodin // is a source block for a definition. 2053*a06bfe05SJan Sjodin SmallVector<unsigned, 4> Sources; 2054*a06bfe05SJan Sjodin if (PHIInfo.findSourcesFromMBB(CodeBB, Sources)) { 2055*a06bfe05SJan Sjodin DEBUG(dbgs() << "Inserting PHI Live Out from BB#" << CodeBB->getNumber() 2056*a06bfe05SJan Sjodin << "\n"); 2057*a06bfe05SJan Sjodin for (auto SI : Sources) { 2058*a06bfe05SJan Sjodin unsigned DestReg; 2059*a06bfe05SJan Sjodin PHIInfo.findDest(SI, CodeBB, DestReg); 2060*a06bfe05SJan Sjodin insertChainedPHI(IfBB, CodeBB, MergeBB, InnerRegion, DestReg, SI); 2061*a06bfe05SJan Sjodin } 2062*a06bfe05SJan Sjodin DEBUG(dbgs() << "Insertion done.\n"); 2063*a06bfe05SJan Sjodin } 2064*a06bfe05SJan Sjodin 2065*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2066*a06bfe05SJan Sjodin } 2067*a06bfe05SJan Sjodin 2068*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::prunePHIInfo(MachineBasicBlock *MBB) { 2069*a06bfe05SJan Sjodin DEBUG(dbgs() << "Before PHI Prune\n"); 2070*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2071*a06bfe05SJan Sjodin SmallVector<std::tuple<unsigned, unsigned, MachineBasicBlock *>, 4> 2072*a06bfe05SJan Sjodin ElimiatedSources; 2073*a06bfe05SJan Sjodin for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 2074*a06bfe05SJan Sjodin ++DRI) { 2075*a06bfe05SJan Sjodin 2076*a06bfe05SJan Sjodin unsigned DestReg = *DRI; 2077*a06bfe05SJan Sjodin auto SE = PHIInfo.sources_end(DestReg); 2078*a06bfe05SJan Sjodin 2079*a06bfe05SJan Sjodin bool MBBContainsPHISource = false; 2080*a06bfe05SJan Sjodin // Check if there is a PHI source in this MBB 2081*a06bfe05SJan Sjodin for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 2082*a06bfe05SJan Sjodin unsigned SourceReg = (*SRI).first; 2083*a06bfe05SJan Sjodin MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 2084*a06bfe05SJan Sjodin if (Def->getParent()->getParent() == MBB) { 2085*a06bfe05SJan Sjodin MBBContainsPHISource = true; 2086*a06bfe05SJan Sjodin } 2087*a06bfe05SJan Sjodin } 2088*a06bfe05SJan Sjodin 2089*a06bfe05SJan Sjodin // If so, all other sources are useless since we know this block 2090*a06bfe05SJan Sjodin // is always executed when the region is executed. 2091*a06bfe05SJan Sjodin if (MBBContainsPHISource) { 2092*a06bfe05SJan Sjodin for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 2093*a06bfe05SJan Sjodin PHILinearize::PHISourceT Source = *SRI; 2094*a06bfe05SJan Sjodin unsigned SourceReg = Source.first; 2095*a06bfe05SJan Sjodin MachineBasicBlock *SourceMBB = Source.second; 2096*a06bfe05SJan Sjodin MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 2097*a06bfe05SJan Sjodin if (Def->getParent()->getParent() != MBB) { 2098*a06bfe05SJan Sjodin ElimiatedSources.push_back( 2099*a06bfe05SJan Sjodin std::make_tuple(DestReg, SourceReg, SourceMBB)); 2100*a06bfe05SJan Sjodin } 2101*a06bfe05SJan Sjodin } 2102*a06bfe05SJan Sjodin } 2103*a06bfe05SJan Sjodin } 2104*a06bfe05SJan Sjodin 2105*a06bfe05SJan Sjodin // Remove the PHI sources that are in the given MBB 2106*a06bfe05SJan Sjodin for (auto &SourceInfo : ElimiatedSources) { 2107*a06bfe05SJan Sjodin PHIInfo.removeSource(std::get<0>(SourceInfo), std::get<1>(SourceInfo), 2108*a06bfe05SJan Sjodin std::get<2>(SourceInfo)); 2109*a06bfe05SJan Sjodin } 2110*a06bfe05SJan Sjodin DEBUG(dbgs() << "After PHI Prune\n"); 2111*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2112*a06bfe05SJan Sjodin } 2113*a06bfe05SJan Sjodin 2114*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegion, 2115*a06bfe05SJan Sjodin unsigned DestReg) { 2116*a06bfe05SJan Sjodin MachineBasicBlock *Entry = CurrentRegion->getEntry(); 2117*a06bfe05SJan Sjodin MachineBasicBlock *Exit = CurrentRegion->getExit(); 2118*a06bfe05SJan Sjodin 2119*a06bfe05SJan Sjodin DEBUG(dbgs() << "RegionExit: " << Exit->getNumber() 2120*a06bfe05SJan Sjodin << " Pred: " << (*(Entry->pred_begin()))->getNumber() << "\n"); 2121*a06bfe05SJan Sjodin 2122*a06bfe05SJan Sjodin int NumSources = 0; 2123*a06bfe05SJan Sjodin auto SE = PHIInfo.sources_end(DestReg); 2124*a06bfe05SJan Sjodin 2125*a06bfe05SJan Sjodin for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 2126*a06bfe05SJan Sjodin NumSources++; 2127*a06bfe05SJan Sjodin } 2128*a06bfe05SJan Sjodin 2129*a06bfe05SJan Sjodin if (NumSources == 1) { 2130*a06bfe05SJan Sjodin auto SRI = PHIInfo.sources_begin(DestReg); 2131*a06bfe05SJan Sjodin unsigned SourceReg = (*SRI).first; 2132*a06bfe05SJan Sjodin replaceRegisterWith(DestReg, SourceReg); 2133*a06bfe05SJan Sjodin } else { 2134*a06bfe05SJan Sjodin const DebugLoc &DL = Entry->findDebugLoc(Entry->begin()); 2135*a06bfe05SJan Sjodin MachineInstrBuilder MIB = BuildMI(*Entry, Entry->instr_begin(), DL, 2136*a06bfe05SJan Sjodin TII->get(TargetOpcode::PHI), DestReg); 2137*a06bfe05SJan Sjodin DEBUG(dbgs() << "Entry PHI " << PrintReg(DestReg, TRI) << "<def> = PHI("); 2138*a06bfe05SJan Sjodin 2139*a06bfe05SJan Sjodin unsigned CurrentBackedgeReg = 0; 2140*a06bfe05SJan Sjodin 2141*a06bfe05SJan Sjodin for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 2142*a06bfe05SJan Sjodin unsigned SourceReg = (*SRI).first; 2143*a06bfe05SJan Sjodin 2144*a06bfe05SJan Sjodin if (CurrentRegion->contains((*SRI).second)) { 2145*a06bfe05SJan Sjodin if (CurrentBackedgeReg == 0) { 2146*a06bfe05SJan Sjodin CurrentBackedgeReg = SourceReg; 2147*a06bfe05SJan Sjodin } else { 2148*a06bfe05SJan Sjodin MachineInstr *PHIDefInstr = getDefInstr(SourceReg); 2149*a06bfe05SJan Sjodin MachineBasicBlock *PHIDefMBB = PHIDefInstr->getParent(); 2150*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = 2151*a06bfe05SJan Sjodin MRI->getRegClass(CurrentBackedgeReg); 2152*a06bfe05SJan Sjodin unsigned NewBackedgeReg = MRI->createVirtualRegister(RegClass); 2153*a06bfe05SJan Sjodin MachineInstrBuilder BackedgePHI = 2154*a06bfe05SJan Sjodin BuildMI(*PHIDefMBB, PHIDefMBB->instr_begin(), DL, 2155*a06bfe05SJan Sjodin TII->get(TargetOpcode::PHI), NewBackedgeReg); 2156*a06bfe05SJan Sjodin BackedgePHI.addReg(CurrentBackedgeReg); 2157*a06bfe05SJan Sjodin BackedgePHI.addMBB(getPHIPred(*PHIDefInstr, 0)); 2158*a06bfe05SJan Sjodin BackedgePHI.addReg(getPHISourceReg(*PHIDefInstr, 1)); 2159*a06bfe05SJan Sjodin BackedgePHI.addMBB((*SRI).second); 2160*a06bfe05SJan Sjodin CurrentBackedgeReg = NewBackedgeReg; 2161*a06bfe05SJan Sjodin DEBUG(dbgs() << "Inserting backedge PHI: " 2162*a06bfe05SJan Sjodin << PrintReg(NewBackedgeReg, TRI) << "<def> = PHI(" 2163*a06bfe05SJan Sjodin << PrintReg(CurrentBackedgeReg, TRI) << ", BB#" 2164*a06bfe05SJan Sjodin << getPHIPred(*PHIDefInstr, 0)->getNumber() << ", " 2165*a06bfe05SJan Sjodin << PrintReg(getPHISourceReg(*PHIDefInstr, 1), TRI) 2166*a06bfe05SJan Sjodin << ", BB#" << (*SRI).second->getNumber()); 2167*a06bfe05SJan Sjodin } 2168*a06bfe05SJan Sjodin } else { 2169*a06bfe05SJan Sjodin MIB.addReg(SourceReg); 2170*a06bfe05SJan Sjodin MIB.addMBB((*SRI).second); 2171*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(SourceReg, TRI) << ", BB#" 2172*a06bfe05SJan Sjodin << (*SRI).second->getNumber() << ", "); 2173*a06bfe05SJan Sjodin } 2174*a06bfe05SJan Sjodin } 2175*a06bfe05SJan Sjodin 2176*a06bfe05SJan Sjodin // Add the final backedge register source to the entry phi 2177*a06bfe05SJan Sjodin if (CurrentBackedgeReg != 0) { 2178*a06bfe05SJan Sjodin MIB.addReg(CurrentBackedgeReg); 2179*a06bfe05SJan Sjodin MIB.addMBB(Exit); 2180*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(CurrentBackedgeReg, TRI) << ", BB#" 2181*a06bfe05SJan Sjodin << Exit->getNumber() << ")\n"); 2182*a06bfe05SJan Sjodin } else { 2183*a06bfe05SJan Sjodin DEBUG(dbgs() << ")\n"); 2184*a06bfe05SJan Sjodin } 2185*a06bfe05SJan Sjodin } 2186*a06bfe05SJan Sjodin } 2187*a06bfe05SJan Sjodin 2188*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::createEntryPHIs(LinearizedRegion *CurrentRegion) { 2189*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2190*a06bfe05SJan Sjodin 2191*a06bfe05SJan Sjodin for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 2192*a06bfe05SJan Sjodin ++DRI) { 2193*a06bfe05SJan Sjodin 2194*a06bfe05SJan Sjodin unsigned DestReg = *DRI; 2195*a06bfe05SJan Sjodin createEntryPHI(CurrentRegion, DestReg); 2196*a06bfe05SJan Sjodin } 2197*a06bfe05SJan Sjodin PHIInfo.clear(); 2198*a06bfe05SJan Sjodin } 2199*a06bfe05SJan Sjodin 2200*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::replaceRegisterWith(unsigned Register, 2201*a06bfe05SJan Sjodin unsigned NewRegister) { 2202*a06bfe05SJan Sjodin assert(Register != NewRegister && "Cannot replace a reg with itself"); 2203*a06bfe05SJan Sjodin 2204*a06bfe05SJan Sjodin for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 2205*a06bfe05SJan Sjodin E = MRI->reg_end(); 2206*a06bfe05SJan Sjodin I != E;) { 2207*a06bfe05SJan Sjodin MachineOperand &O = *I; 2208*a06bfe05SJan Sjodin ++I; 2209*a06bfe05SJan Sjodin if (TargetRegisterInfo::isPhysicalRegister(NewRegister)) { 2210*a06bfe05SJan Sjodin DEBUG(dbgs() << "Trying to substitute physical register: " 2211*a06bfe05SJan Sjodin << PrintReg(NewRegister, MRI->getTargetRegisterInfo()) 2212*a06bfe05SJan Sjodin << "\n"); 2213*a06bfe05SJan Sjodin llvm_unreachable("Cannot substitute physical registers"); 2214*a06bfe05SJan Sjodin // We don't handle physical registers, but if we need to 2215*a06bfe05SJan Sjodin // in the future This is how we do it: 2216*a06bfe05SJan Sjodin // O.substPhysReg(NewRegister, *TRI); 2217*a06bfe05SJan Sjodin } else { 2218*a06bfe05SJan Sjodin DEBUG(dbgs() << "Replacing register: " 2219*a06bfe05SJan Sjodin << PrintReg(Register, MRI->getTargetRegisterInfo()) 2220*a06bfe05SJan Sjodin << " with " 2221*a06bfe05SJan Sjodin << PrintReg(NewRegister, MRI->getTargetRegisterInfo()) 2222*a06bfe05SJan Sjodin << "\n"); 2223*a06bfe05SJan Sjodin O.setReg(NewRegister); 2224*a06bfe05SJan Sjodin } 2225*a06bfe05SJan Sjodin } 2226*a06bfe05SJan Sjodin PHIInfo.deleteDef(Register); 2227*a06bfe05SJan Sjodin 2228*a06bfe05SJan Sjodin getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 2229*a06bfe05SJan Sjodin 2230*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2231*a06bfe05SJan Sjodin } 2232*a06bfe05SJan Sjodin 2233*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::resolvePHIInfos(MachineBasicBlock *FunctionEntry) { 2234*a06bfe05SJan Sjodin DEBUG(dbgs() << "Resolve PHI Infos\n"); 2235*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2236*a06bfe05SJan Sjodin for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 2237*a06bfe05SJan Sjodin ++DRI) { 2238*a06bfe05SJan Sjodin unsigned DestReg = *DRI; 2239*a06bfe05SJan Sjodin DEBUG(dbgs() << "DestReg: " << PrintReg(DestReg, TRI) << "\n"); 2240*a06bfe05SJan Sjodin auto SRI = PHIInfo.sources_begin(DestReg); 2241*a06bfe05SJan Sjodin unsigned SourceReg = (*SRI).first; 2242*a06bfe05SJan Sjodin DEBUG(dbgs() << "DestReg: " << PrintReg(DestReg, TRI) 2243*a06bfe05SJan Sjodin << " SourceReg: " << PrintReg(SourceReg, TRI) << "\n"); 2244*a06bfe05SJan Sjodin 2245*a06bfe05SJan Sjodin assert(PHIInfo.sources_end(DestReg) == ++SRI && 2246*a06bfe05SJan Sjodin "More than one phi source in entry node"); 2247*a06bfe05SJan Sjodin replaceRegisterWith(DestReg, SourceReg); 2248*a06bfe05SJan Sjodin } 2249*a06bfe05SJan Sjodin } 2250*a06bfe05SJan Sjodin 2251*a06bfe05SJan Sjodin static bool isFunctionEntryBlock(MachineBasicBlock *MBB) { 2252*a06bfe05SJan Sjodin return ((&(*(MBB->getParent()->begin()))) == MBB); 2253*a06bfe05SJan Sjodin } 2254*a06bfe05SJan Sjodin 2255*a06bfe05SJan Sjodin MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 2256*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBB, 2257*a06bfe05SJan Sjodin LinearizedRegion *CurrentRegion, unsigned BBSelectRegIn, 2258*a06bfe05SJan Sjodin unsigned BBSelectRegOut) { 2259*a06bfe05SJan Sjodin if (isFunctionEntryBlock(CodeBB) && !CurrentRegion->getHasLoop()) { 2260*a06bfe05SJan Sjodin // Handle non-loop function entry block. 2261*a06bfe05SJan Sjodin // We need to allow loops to the entry block and then 2262*a06bfe05SJan Sjodin rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 2263*a06bfe05SJan Sjodin resolvePHIInfos(CodeBB); 2264*a06bfe05SJan Sjodin removeExternalCFGSuccessors(CodeBB); 2265*a06bfe05SJan Sjodin CodeBB->addSuccessor(MergeBB); 2266*a06bfe05SJan Sjodin CurrentRegion->addMBB(CodeBB); 2267*a06bfe05SJan Sjodin return nullptr; 2268*a06bfe05SJan Sjodin } 2269*a06bfe05SJan Sjodin if (CurrentRegion->getEntry() == CodeBB && !CurrentRegion->getHasLoop()) { 2270*a06bfe05SJan Sjodin // Handle non-loop region entry block. 2271*a06bfe05SJan Sjodin MachineFunction *MF = MergeBB->getParent(); 2272*a06bfe05SJan Sjodin auto MergeIter = MergeBB->getIterator(); 2273*a06bfe05SJan Sjodin auto CodeBBStartIter = CodeBB->getIterator(); 2274*a06bfe05SJan Sjodin auto CodeBBEndIter = ++(CodeBB->getIterator()); 2275*a06bfe05SJan Sjodin if (CodeBBEndIter != MergeIter) { 2276*a06bfe05SJan Sjodin MF->splice(MergeIter, CodeBBStartIter, CodeBBEndIter); 2277*a06bfe05SJan Sjodin } 2278*a06bfe05SJan Sjodin rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 2279*a06bfe05SJan Sjodin prunePHIInfo(CodeBB); 2280*a06bfe05SJan Sjodin createEntryPHIs(CurrentRegion); 2281*a06bfe05SJan Sjodin removeExternalCFGSuccessors(CodeBB); 2282*a06bfe05SJan Sjodin CodeBB->addSuccessor(MergeBB); 2283*a06bfe05SJan Sjodin CurrentRegion->addMBB(CodeBB); 2284*a06bfe05SJan Sjodin return nullptr; 2285*a06bfe05SJan Sjodin } else { 2286*a06bfe05SJan Sjodin // Handle internal block. 2287*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectRegIn); 2288*a06bfe05SJan Sjodin unsigned CodeBBSelectReg = MRI->createVirtualRegister(RegClass); 2289*a06bfe05SJan Sjodin rewriteCodeBBTerminator(CodeBB, MergeBB, CodeBBSelectReg); 2290*a06bfe05SJan Sjodin bool IsRegionEntryBB = CurrentRegion->getEntry() == CodeBB; 2291*a06bfe05SJan Sjodin MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeBB, CodeBB, CodeBB, 2292*a06bfe05SJan Sjodin BBSelectRegIn, IsRegionEntryBB); 2293*a06bfe05SJan Sjodin CurrentRegion->addMBB(IfBB); 2294*a06bfe05SJan Sjodin // If this is the entry block we need to make the If block the new 2295*a06bfe05SJan Sjodin // linearized region entry. 2296*a06bfe05SJan Sjodin if (IsRegionEntryBB) { 2297*a06bfe05SJan Sjodin CurrentRegion->setEntry(IfBB); 2298*a06bfe05SJan Sjodin 2299*a06bfe05SJan Sjodin if (CurrentRegion->getHasLoop()) { 2300*a06bfe05SJan Sjodin MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 2301*a06bfe05SJan Sjodin MachineBasicBlock *ETrueBB = nullptr; 2302*a06bfe05SJan Sjodin MachineBasicBlock *EFalseBB = nullptr; 2303*a06bfe05SJan Sjodin SmallVector<MachineOperand, 1> ECond; 2304*a06bfe05SJan Sjodin 2305*a06bfe05SJan Sjodin const DebugLoc &DL = DebugLoc(); 2306*a06bfe05SJan Sjodin TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 2307*a06bfe05SJan Sjodin TII->removeBranch(*RegionExit); 2308*a06bfe05SJan Sjodin 2309*a06bfe05SJan Sjodin // We need to create a backedge if there is a loop 2310*a06bfe05SJan Sjodin unsigned Reg = TII->insertNE( 2311*a06bfe05SJan Sjodin RegionExit, RegionExit->instr_end(), DL, 2312*a06bfe05SJan Sjodin CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 2313*a06bfe05SJan Sjodin CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 2314*a06bfe05SJan Sjodin MachineOperand RegOp = 2315*a06bfe05SJan Sjodin MachineOperand::CreateReg(Reg, false, false, true); 2316*a06bfe05SJan Sjodin ArrayRef<MachineOperand> Cond(RegOp); 2317*a06bfe05SJan Sjodin DEBUG(dbgs() << "RegionExitReg: "); 2318*a06bfe05SJan Sjodin DEBUG(Cond[0].print(dbgs(), TRI)); 2319*a06bfe05SJan Sjodin DEBUG(dbgs() << "\n"); 2320*a06bfe05SJan Sjodin TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 2321*a06bfe05SJan Sjodin Cond, DebugLoc()); 2322*a06bfe05SJan Sjodin RegionExit->addSuccessor(CurrentRegion->getEntry()); 2323*a06bfe05SJan Sjodin } 2324*a06bfe05SJan Sjodin } 2325*a06bfe05SJan Sjodin CurrentRegion->addMBB(CodeBB); 2326*a06bfe05SJan Sjodin LinearizedRegion InnerRegion(CodeBB, MRI, TRI, PHIInfo); 2327*a06bfe05SJan Sjodin 2328*a06bfe05SJan Sjodin InnerRegion.setParent(CurrentRegion); 2329*a06bfe05SJan Sjodin DEBUG(dbgs() << "Insert BB Select PHI (BB)\n"); 2330*a06bfe05SJan Sjodin insertMergePHI(IfBB, CodeBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 2331*a06bfe05SJan Sjodin CodeBBSelectReg); 2332*a06bfe05SJan Sjodin InnerRegion.addMBB(MergeBB); 2333*a06bfe05SJan Sjodin 2334*a06bfe05SJan Sjodin DEBUG(InnerRegion.print(dbgs(), TRI)); 2335*a06bfe05SJan Sjodin rewriteLiveOutRegs(IfBB, CodeBB, MergeBB, &InnerRegion, CurrentRegion); 2336*a06bfe05SJan Sjodin extractKilledPHIs(CodeBB); 2337*a06bfe05SJan Sjodin if (IsRegionEntryBB) { 2338*a06bfe05SJan Sjodin createEntryPHIs(CurrentRegion); 2339*a06bfe05SJan Sjodin } 2340*a06bfe05SJan Sjodin return IfBB; 2341*a06bfe05SJan Sjodin } 2342*a06bfe05SJan Sjodin } 2343*a06bfe05SJan Sjodin 2344*a06bfe05SJan Sjodin MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 2345*a06bfe05SJan Sjodin MachineBasicBlock *MergeBB, LinearizedRegion *InnerRegion, 2346*a06bfe05SJan Sjodin LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 2347*a06bfe05SJan Sjodin unsigned BBSelectRegIn, unsigned BBSelectRegOut) { 2348*a06bfe05SJan Sjodin unsigned CodeBBSelectReg = 2349*a06bfe05SJan Sjodin InnerRegion->getRegionMRT()->getInnerOutputRegister(); 2350*a06bfe05SJan Sjodin MachineBasicBlock *CodeEntryBB = InnerRegion->getEntry(); 2351*a06bfe05SJan Sjodin MachineBasicBlock *CodeExitBB = InnerRegion->getExit(); 2352*a06bfe05SJan Sjodin MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeEntryBB, CodeExitBB, 2353*a06bfe05SJan Sjodin SelectBB, BBSelectRegIn, true); 2354*a06bfe05SJan Sjodin CurrentRegion->addMBB(IfBB); 2355*a06bfe05SJan Sjodin bool isEntry = CurrentRegion->getEntry() == InnerRegion->getEntry(); 2356*a06bfe05SJan Sjodin if (isEntry) { 2357*a06bfe05SJan Sjodin 2358*a06bfe05SJan Sjodin if (CurrentRegion->getHasLoop()) { 2359*a06bfe05SJan Sjodin MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 2360*a06bfe05SJan Sjodin MachineBasicBlock *ETrueBB = nullptr; 2361*a06bfe05SJan Sjodin MachineBasicBlock *EFalseBB = nullptr; 2362*a06bfe05SJan Sjodin SmallVector<MachineOperand, 1> ECond; 2363*a06bfe05SJan Sjodin 2364*a06bfe05SJan Sjodin const DebugLoc &DL = DebugLoc(); 2365*a06bfe05SJan Sjodin TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 2366*a06bfe05SJan Sjodin TII->removeBranch(*RegionExit); 2367*a06bfe05SJan Sjodin 2368*a06bfe05SJan Sjodin // We need to create a backedge if there is a loop 2369*a06bfe05SJan Sjodin unsigned Reg = 2370*a06bfe05SJan Sjodin TII->insertNE(RegionExit, RegionExit->instr_end(), DL, 2371*a06bfe05SJan Sjodin CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 2372*a06bfe05SJan Sjodin CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 2373*a06bfe05SJan Sjodin MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 2374*a06bfe05SJan Sjodin ArrayRef<MachineOperand> Cond(RegOp); 2375*a06bfe05SJan Sjodin DEBUG(dbgs() << "RegionExitReg: "); 2376*a06bfe05SJan Sjodin DEBUG(Cond[0].print(dbgs(), TRI)); 2377*a06bfe05SJan Sjodin DEBUG(dbgs() << "\n"); 2378*a06bfe05SJan Sjodin TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 2379*a06bfe05SJan Sjodin Cond, DebugLoc()); 2380*a06bfe05SJan Sjodin RegionExit->addSuccessor(IfBB); 2381*a06bfe05SJan Sjodin } 2382*a06bfe05SJan Sjodin } 2383*a06bfe05SJan Sjodin CurrentRegion->addMBBs(InnerRegion); 2384*a06bfe05SJan Sjodin DEBUG(dbgs() << "Insert BB Select PHI (region)\n"); 2385*a06bfe05SJan Sjodin insertMergePHI(IfBB, CodeExitBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 2386*a06bfe05SJan Sjodin CodeBBSelectReg); 2387*a06bfe05SJan Sjodin 2388*a06bfe05SJan Sjodin rewriteLiveOutRegs(IfBB, /* CodeEntryBB */ CodeExitBB, MergeBB, InnerRegion, 2389*a06bfe05SJan Sjodin CurrentRegion); 2390*a06bfe05SJan Sjodin 2391*a06bfe05SJan Sjodin rewriteRegionEntryPHIs(InnerRegion, IfBB); 2392*a06bfe05SJan Sjodin 2393*a06bfe05SJan Sjodin if (isEntry) { 2394*a06bfe05SJan Sjodin CurrentRegion->setEntry(IfBB); 2395*a06bfe05SJan Sjodin } 2396*a06bfe05SJan Sjodin 2397*a06bfe05SJan Sjodin if (isEntry) { 2398*a06bfe05SJan Sjodin createEntryPHIs(CurrentRegion); 2399*a06bfe05SJan Sjodin } 2400*a06bfe05SJan Sjodin 2401*a06bfe05SJan Sjodin return IfBB; 2402*a06bfe05SJan Sjodin } 2403*a06bfe05SJan Sjodin 2404*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::splitLoopPHI(MachineInstr &PHI, 2405*a06bfe05SJan Sjodin MachineBasicBlock *Entry, 2406*a06bfe05SJan Sjodin MachineBasicBlock *EntrySucc, 2407*a06bfe05SJan Sjodin LinearizedRegion *LRegion) { 2408*a06bfe05SJan Sjodin SmallVector<unsigned, 2> PHIRegionIndices; 2409*a06bfe05SJan Sjodin getPHIRegionIndices(LRegion, PHI, PHIRegionIndices); 2410*a06bfe05SJan Sjodin 2411*a06bfe05SJan Sjodin assert(PHIRegionIndices.size() == 1); 2412*a06bfe05SJan Sjodin 2413*a06bfe05SJan Sjodin unsigned RegionIndex = PHIRegionIndices[0]; 2414*a06bfe05SJan Sjodin unsigned RegionSourceReg = getPHISourceReg(PHI, RegionIndex); 2415*a06bfe05SJan Sjodin MachineBasicBlock *RegionSourceMBB = getPHIPred(PHI, RegionIndex); 2416*a06bfe05SJan Sjodin unsigned PHIDest = getPHIDestReg(PHI); 2417*a06bfe05SJan Sjodin unsigned PHISource = PHIDest; 2418*a06bfe05SJan Sjodin unsigned ReplaceReg; 2419*a06bfe05SJan Sjodin 2420*a06bfe05SJan Sjodin if (shrinkPHI(PHI, PHIRegionIndices, &ReplaceReg)) { 2421*a06bfe05SJan Sjodin PHISource = ReplaceReg; 2422*a06bfe05SJan Sjodin } 2423*a06bfe05SJan Sjodin 2424*a06bfe05SJan Sjodin const TargetRegisterClass *RegClass = MRI->getRegClass(PHIDest); 2425*a06bfe05SJan Sjodin unsigned NewDestReg = MRI->createVirtualRegister(RegClass); 2426*a06bfe05SJan Sjodin LRegion->replaceRegisterInsideRegion(PHIDest, NewDestReg, false, MRI); 2427*a06bfe05SJan Sjodin MachineInstrBuilder MIB = 2428*a06bfe05SJan Sjodin BuildMI(*EntrySucc, EntrySucc->instr_begin(), PHI.getDebugLoc(), 2429*a06bfe05SJan Sjodin TII->get(TargetOpcode::PHI), NewDestReg); 2430*a06bfe05SJan Sjodin DEBUG(dbgs() << "Split Entry PHI " << PrintReg(NewDestReg, TRI) 2431*a06bfe05SJan Sjodin << "<def> = PHI("); 2432*a06bfe05SJan Sjodin MIB.addReg(PHISource); 2433*a06bfe05SJan Sjodin MIB.addMBB(Entry); 2434*a06bfe05SJan Sjodin DEBUG(dbgs() << PrintReg(PHISource, TRI) << ", BB#" << Entry->getNumber()); 2435*a06bfe05SJan Sjodin MIB.addReg(RegionSourceReg); 2436*a06bfe05SJan Sjodin MIB.addMBB(RegionSourceMBB); 2437*a06bfe05SJan Sjodin DEBUG(dbgs() << " ," << PrintReg(RegionSourceReg, TRI) << ", BB#" 2438*a06bfe05SJan Sjodin << RegionSourceMBB->getNumber() << ")\n"); 2439*a06bfe05SJan Sjodin } 2440*a06bfe05SJan Sjodin 2441*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::splitLoopPHIs(MachineBasicBlock *Entry, 2442*a06bfe05SJan Sjodin MachineBasicBlock *EntrySucc, 2443*a06bfe05SJan Sjodin LinearizedRegion *LRegion) { 2444*a06bfe05SJan Sjodin SmallVector<MachineInstr *, 2> PHIs; 2445*a06bfe05SJan Sjodin collectPHIs(Entry, PHIs); 2446*a06bfe05SJan Sjodin 2447*a06bfe05SJan Sjodin for (auto PHII : PHIs) { 2448*a06bfe05SJan Sjodin splitLoopPHI(*PHII, Entry, EntrySucc, LRegion); 2449*a06bfe05SJan Sjodin } 2450*a06bfe05SJan Sjodin } 2451*a06bfe05SJan Sjodin 2452*a06bfe05SJan Sjodin // Split the exit block so that we can insert a end control flow 2453*a06bfe05SJan Sjodin MachineBasicBlock * 2454*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer::splitExit(LinearizedRegion *LRegion) { 2455*a06bfe05SJan Sjodin auto MRTRegion = LRegion->getRegionMRT(); 2456*a06bfe05SJan Sjodin auto Exit = LRegion->getExit(); 2457*a06bfe05SJan Sjodin auto MF = Exit->getParent(); 2458*a06bfe05SJan Sjodin auto Succ = MRTRegion->getSucc(); 2459*a06bfe05SJan Sjodin 2460*a06bfe05SJan Sjodin auto NewExit = MF->CreateMachineBasicBlock(); 2461*a06bfe05SJan Sjodin auto AfterExitIter = Exit->getIterator(); 2462*a06bfe05SJan Sjodin AfterExitIter++; 2463*a06bfe05SJan Sjodin MF->insert(AfterExitIter, NewExit); 2464*a06bfe05SJan Sjodin Exit->removeSuccessor(Succ); 2465*a06bfe05SJan Sjodin Exit->addSuccessor(NewExit); 2466*a06bfe05SJan Sjodin NewExit->addSuccessor(Succ); 2467*a06bfe05SJan Sjodin insertUnconditionalBranch(NewExit, Succ); 2468*a06bfe05SJan Sjodin LRegion->addMBB(NewExit); 2469*a06bfe05SJan Sjodin LRegion->setExit(NewExit); 2470*a06bfe05SJan Sjodin 2471*a06bfe05SJan Sjodin DEBUG(dbgs() << "Created new exit block: " << NewExit->getNumber() << "\n"); 2472*a06bfe05SJan Sjodin 2473*a06bfe05SJan Sjodin // Replace any PHI Predecessors in the successor with NewExit 2474*a06bfe05SJan Sjodin for (auto &II : *Succ) { 2475*a06bfe05SJan Sjodin MachineInstr &Instr = II; 2476*a06bfe05SJan Sjodin 2477*a06bfe05SJan Sjodin // If we are past the PHI instructions we are done 2478*a06bfe05SJan Sjodin if (!Instr.isPHI()) 2479*a06bfe05SJan Sjodin break; 2480*a06bfe05SJan Sjodin 2481*a06bfe05SJan Sjodin int numPreds = getPHINumInputs(Instr); 2482*a06bfe05SJan Sjodin for (int i = 0; i < numPreds; ++i) { 2483*a06bfe05SJan Sjodin auto Pred = getPHIPred(Instr, i); 2484*a06bfe05SJan Sjodin if (Pred == Exit) { 2485*a06bfe05SJan Sjodin setPhiPred(Instr, i, NewExit); 2486*a06bfe05SJan Sjodin } 2487*a06bfe05SJan Sjodin } 2488*a06bfe05SJan Sjodin } 2489*a06bfe05SJan Sjodin 2490*a06bfe05SJan Sjodin return NewExit; 2491*a06bfe05SJan Sjodin } 2492*a06bfe05SJan Sjodin 2493*a06bfe05SJan Sjodin 2494*a06bfe05SJan Sjodin static MachineBasicBlock *split(MachineBasicBlock::iterator I) { 2495*a06bfe05SJan Sjodin // Create the fall-through block. 2496*a06bfe05SJan Sjodin MachineBasicBlock *MBB = (*I).getParent(); 2497*a06bfe05SJan Sjodin MachineFunction *MF = MBB->getParent(); 2498*a06bfe05SJan Sjodin MachineBasicBlock *SuccMBB = MF->CreateMachineBasicBlock(); 2499*a06bfe05SJan Sjodin auto MBBIter = ++(MBB->getIterator()); 2500*a06bfe05SJan Sjodin MF->insert(MBBIter, SuccMBB); 2501*a06bfe05SJan Sjodin SuccMBB->transferSuccessorsAndUpdatePHIs(MBB); 2502*a06bfe05SJan Sjodin MBB->addSuccessor(SuccMBB); 2503*a06bfe05SJan Sjodin 2504*a06bfe05SJan Sjodin // Splice the code over. 2505*a06bfe05SJan Sjodin SuccMBB->splice(SuccMBB->end(), MBB, I, MBB->end()); 2506*a06bfe05SJan Sjodin 2507*a06bfe05SJan Sjodin return SuccMBB; 2508*a06bfe05SJan Sjodin } 2509*a06bfe05SJan Sjodin 2510*a06bfe05SJan Sjodin // Split the entry block separating PHI-nodes and the rest of the code 2511*a06bfe05SJan Sjodin // This is needed to insert an initializer for the bb select register 2512*a06bfe05SJan Sjodin // inloop regions. 2513*a06bfe05SJan Sjodin 2514*a06bfe05SJan Sjodin MachineBasicBlock * 2515*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer::splitEntry(LinearizedRegion *LRegion) { 2516*a06bfe05SJan Sjodin MachineBasicBlock *Entry = LRegion->getEntry(); 2517*a06bfe05SJan Sjodin MachineBasicBlock *EntrySucc = split(Entry->getFirstNonPHI()); 2518*a06bfe05SJan Sjodin MachineBasicBlock *Exit = LRegion->getExit(); 2519*a06bfe05SJan Sjodin 2520*a06bfe05SJan Sjodin DEBUG(dbgs() << "Split BB#" << Entry->getNumber() << " to BB#" 2521*a06bfe05SJan Sjodin << Entry->getNumber() << " -> BB#" << EntrySucc->getNumber() 2522*a06bfe05SJan Sjodin << "\n"); 2523*a06bfe05SJan Sjodin LRegion->addMBB(EntrySucc); 2524*a06bfe05SJan Sjodin 2525*a06bfe05SJan Sjodin // Make the backedge go to Entry Succ 2526*a06bfe05SJan Sjodin if (Exit->isSuccessor(Entry)) { 2527*a06bfe05SJan Sjodin Exit->removeSuccessor(Entry); 2528*a06bfe05SJan Sjodin } 2529*a06bfe05SJan Sjodin Exit->addSuccessor(EntrySucc); 2530*a06bfe05SJan Sjodin MachineInstr &Branch = *(Exit->instr_rbegin()); 2531*a06bfe05SJan Sjodin for (auto &UI : Branch.uses()) { 2532*a06bfe05SJan Sjodin if (UI.isMBB() && UI.getMBB() == Entry) { 2533*a06bfe05SJan Sjodin UI.setMBB(EntrySucc); 2534*a06bfe05SJan Sjodin } 2535*a06bfe05SJan Sjodin } 2536*a06bfe05SJan Sjodin 2537*a06bfe05SJan Sjodin splitLoopPHIs(Entry, EntrySucc, LRegion); 2538*a06bfe05SJan Sjodin 2539*a06bfe05SJan Sjodin return EntrySucc; 2540*a06bfe05SJan Sjodin } 2541*a06bfe05SJan Sjodin 2542*a06bfe05SJan Sjodin LinearizedRegion * 2543*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer::initLinearizedRegion(RegionMRT *Region) { 2544*a06bfe05SJan Sjodin LinearizedRegion *LRegion = Region->getLinearizedRegion(); 2545*a06bfe05SJan Sjodin LRegion->initLiveOut(Region, MRI, TRI, PHIInfo); 2546*a06bfe05SJan Sjodin LRegion->setEntry(Region->getEntry()); 2547*a06bfe05SJan Sjodin return LRegion; 2548*a06bfe05SJan Sjodin } 2549*a06bfe05SJan Sjodin 2550*a06bfe05SJan Sjodin static void removeOldExitPreds(RegionMRT *Region) { 2551*a06bfe05SJan Sjodin MachineBasicBlock *Exit = Region->getSucc(); 2552*a06bfe05SJan Sjodin if (Exit == nullptr) { 2553*a06bfe05SJan Sjodin return; 2554*a06bfe05SJan Sjodin } 2555*a06bfe05SJan Sjodin for (MachineBasicBlock::pred_iterator PI = Exit->pred_begin(), 2556*a06bfe05SJan Sjodin E = Exit->pred_end(); 2557*a06bfe05SJan Sjodin PI != E; ++PI) { 2558*a06bfe05SJan Sjodin if (Region->contains(*PI)) { 2559*a06bfe05SJan Sjodin (*PI)->removeSuccessor(Exit); 2560*a06bfe05SJan Sjodin } 2561*a06bfe05SJan Sjodin } 2562*a06bfe05SJan Sjodin } 2563*a06bfe05SJan Sjodin 2564*a06bfe05SJan Sjodin static bool mbbHasBackEdge(MachineBasicBlock *MBB, 2565*a06bfe05SJan Sjodin SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 2566*a06bfe05SJan Sjodin for (auto SI = MBB->succ_begin(), SE = MBB->succ_end(); SI != SE; ++SI) { 2567*a06bfe05SJan Sjodin if (MBBs.count(*SI) != 0) { 2568*a06bfe05SJan Sjodin return true; 2569*a06bfe05SJan Sjodin } 2570*a06bfe05SJan Sjodin } 2571*a06bfe05SJan Sjodin return false; 2572*a06bfe05SJan Sjodin } 2573*a06bfe05SJan Sjodin 2574*a06bfe05SJan Sjodin static bool containsNewBackedge(MRT *Tree, 2575*a06bfe05SJan Sjodin SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 2576*a06bfe05SJan Sjodin // Need to traverse this in reverse since it is in post order. 2577*a06bfe05SJan Sjodin if (Tree == nullptr) 2578*a06bfe05SJan Sjodin return false; 2579*a06bfe05SJan Sjodin 2580*a06bfe05SJan Sjodin if (Tree->isMBB()) { 2581*a06bfe05SJan Sjodin MachineBasicBlock *MBB = Tree->getMBBMRT()->getMBB(); 2582*a06bfe05SJan Sjodin MBBs.insert(MBB); 2583*a06bfe05SJan Sjodin if (mbbHasBackEdge(MBB, MBBs)) { 2584*a06bfe05SJan Sjodin return true; 2585*a06bfe05SJan Sjodin } 2586*a06bfe05SJan Sjodin } else { 2587*a06bfe05SJan Sjodin RegionMRT *Region = Tree->getRegionMRT(); 2588*a06bfe05SJan Sjodin SetVector<MRT *> *Children = Region->getChildren(); 2589*a06bfe05SJan Sjodin for (auto CI = Children->rbegin(), CE = Children->rend(); CI != CE; ++CI) { 2590*a06bfe05SJan Sjodin if (containsNewBackedge(*CI, MBBs)) 2591*a06bfe05SJan Sjodin return true; 2592*a06bfe05SJan Sjodin } 2593*a06bfe05SJan Sjodin } 2594*a06bfe05SJan Sjodin return false; 2595*a06bfe05SJan Sjodin } 2596*a06bfe05SJan Sjodin 2597*a06bfe05SJan Sjodin static bool containsNewBackedge(RegionMRT *Region) { 2598*a06bfe05SJan Sjodin SmallPtrSet<MachineBasicBlock *, 8> MBBs; 2599*a06bfe05SJan Sjodin return containsNewBackedge(Region, MBBs); 2600*a06bfe05SJan Sjodin } 2601*a06bfe05SJan Sjodin 2602*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::structurizeComplexRegion(RegionMRT *Region) { 2603*a06bfe05SJan Sjodin auto *LRegion = initLinearizedRegion(Region); 2604*a06bfe05SJan Sjodin LRegion->setHasLoop(containsNewBackedge(Region)); 2605*a06bfe05SJan Sjodin MachineBasicBlock *LastMerge = createLinearizedExitBlock(Region); 2606*a06bfe05SJan Sjodin MachineBasicBlock *CurrentMerge = LastMerge; 2607*a06bfe05SJan Sjodin LRegion->addMBB(LastMerge); 2608*a06bfe05SJan Sjodin LRegion->setExit(LastMerge); 2609*a06bfe05SJan Sjodin 2610*a06bfe05SJan Sjodin rewriteRegionExitPHIs(Region, LastMerge, LRegion); 2611*a06bfe05SJan Sjodin removeOldExitPreds(Region); 2612*a06bfe05SJan Sjodin 2613*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2614*a06bfe05SJan Sjodin 2615*a06bfe05SJan Sjodin SetVector<MRT *> *Children = Region->getChildren(); 2616*a06bfe05SJan Sjodin DEBUG(dbgs() << "===========If Region Start===============\n"); 2617*a06bfe05SJan Sjodin if (LRegion->getHasLoop()) { 2618*a06bfe05SJan Sjodin DEBUG(dbgs() << "Has Backedge: Yes\n"); 2619*a06bfe05SJan Sjodin } else { 2620*a06bfe05SJan Sjodin DEBUG(dbgs() << "Has Backedge: No\n"); 2621*a06bfe05SJan Sjodin } 2622*a06bfe05SJan Sjodin 2623*a06bfe05SJan Sjodin unsigned BBSelectRegIn; 2624*a06bfe05SJan Sjodin unsigned BBSelectRegOut; 2625*a06bfe05SJan Sjodin for (auto CI = Children->begin(), CE = Children->end(); CI != CE; ++CI) { 2626*a06bfe05SJan Sjodin DEBUG(dbgs() << "CurrentRegion: \n"); 2627*a06bfe05SJan Sjodin DEBUG(LRegion->print(dbgs(), TRI)); 2628*a06bfe05SJan Sjodin 2629*a06bfe05SJan Sjodin auto CNI = CI; 2630*a06bfe05SJan Sjodin ++CNI; 2631*a06bfe05SJan Sjodin 2632*a06bfe05SJan Sjodin MRT *Child = (*CI); 2633*a06bfe05SJan Sjodin 2634*a06bfe05SJan Sjodin if (Child->isRegion()) { 2635*a06bfe05SJan Sjodin 2636*a06bfe05SJan Sjodin LinearizedRegion *InnerLRegion = 2637*a06bfe05SJan Sjodin Child->getRegionMRT()->getLinearizedRegion(); 2638*a06bfe05SJan Sjodin // We found the block is the exit of an inner region, we need 2639*a06bfe05SJan Sjodin // to put it in the current linearized region. 2640*a06bfe05SJan Sjodin 2641*a06bfe05SJan Sjodin DEBUG(dbgs() << "Linearizing region: "); 2642*a06bfe05SJan Sjodin DEBUG(InnerLRegion->print(dbgs(), TRI)); 2643*a06bfe05SJan Sjodin DEBUG(dbgs() << "\n"); 2644*a06bfe05SJan Sjodin 2645*a06bfe05SJan Sjodin MachineBasicBlock *InnerEntry = InnerLRegion->getEntry(); 2646*a06bfe05SJan Sjodin if ((&(*(InnerEntry->getParent()->begin()))) == InnerEntry) { 2647*a06bfe05SJan Sjodin // Entry has already been linearized, no need to do this region. 2648*a06bfe05SJan Sjodin unsigned OuterSelect = InnerLRegion->getBBSelectRegOut(); 2649*a06bfe05SJan Sjodin unsigned InnerSelectReg = 2650*a06bfe05SJan Sjodin InnerLRegion->getRegionMRT()->getInnerOutputRegister(); 2651*a06bfe05SJan Sjodin replaceRegisterWith(InnerSelectReg, OuterSelect), 2652*a06bfe05SJan Sjodin resolvePHIInfos(InnerEntry); 2653*a06bfe05SJan Sjodin if (!InnerLRegion->getExit()->isSuccessor(CurrentMerge)) 2654*a06bfe05SJan Sjodin InnerLRegion->getExit()->addSuccessor(CurrentMerge); 2655*a06bfe05SJan Sjodin continue; 2656*a06bfe05SJan Sjodin } 2657*a06bfe05SJan Sjodin 2658*a06bfe05SJan Sjodin BBSelectRegOut = Child->getBBSelectRegOut(); 2659*a06bfe05SJan Sjodin BBSelectRegIn = Child->getBBSelectRegIn(); 2660*a06bfe05SJan Sjodin 2661*a06bfe05SJan Sjodin DEBUG(dbgs() << "BBSelectRegIn: " << PrintReg(BBSelectRegIn, TRI) 2662*a06bfe05SJan Sjodin << "\n"); 2663*a06bfe05SJan Sjodin DEBUG(dbgs() << "BBSelectRegOut: " << PrintReg(BBSelectRegOut, TRI) 2664*a06bfe05SJan Sjodin << "\n"); 2665*a06bfe05SJan Sjodin 2666*a06bfe05SJan Sjodin MachineBasicBlock *IfEnd = CurrentMerge; 2667*a06bfe05SJan Sjodin CurrentMerge = createIfRegion(CurrentMerge, InnerLRegion, LRegion, 2668*a06bfe05SJan Sjodin Child->getRegionMRT()->getEntry(), 2669*a06bfe05SJan Sjodin BBSelectRegIn, BBSelectRegOut); 2670*a06bfe05SJan Sjodin TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 2671*a06bfe05SJan Sjodin } else { 2672*a06bfe05SJan Sjodin MachineBasicBlock *MBB = Child->getMBBMRT()->getMBB(); 2673*a06bfe05SJan Sjodin DEBUG(dbgs() << "Linearizing block: " << MBB->getNumber() << "\n"); 2674*a06bfe05SJan Sjodin 2675*a06bfe05SJan Sjodin if (MBB == getSingleExitNode(*(MBB->getParent()))) { 2676*a06bfe05SJan Sjodin // If this is the exit block then we need to skip to the next. 2677*a06bfe05SJan Sjodin // The "in" register will be transferred to "out" in the next 2678*a06bfe05SJan Sjodin // iteration. 2679*a06bfe05SJan Sjodin continue; 2680*a06bfe05SJan Sjodin } 2681*a06bfe05SJan Sjodin 2682*a06bfe05SJan Sjodin BBSelectRegOut = Child->getBBSelectRegOut(); 2683*a06bfe05SJan Sjodin BBSelectRegIn = Child->getBBSelectRegIn(); 2684*a06bfe05SJan Sjodin 2685*a06bfe05SJan Sjodin DEBUG(dbgs() << "BBSelectRegIn: " << PrintReg(BBSelectRegIn, TRI) 2686*a06bfe05SJan Sjodin << "\n"); 2687*a06bfe05SJan Sjodin DEBUG(dbgs() << "BBSelectRegOut: " << PrintReg(BBSelectRegOut, TRI) 2688*a06bfe05SJan Sjodin << "\n"); 2689*a06bfe05SJan Sjodin 2690*a06bfe05SJan Sjodin MachineBasicBlock *IfEnd = CurrentMerge; 2691*a06bfe05SJan Sjodin // This is a basic block that is not part of an inner region, we 2692*a06bfe05SJan Sjodin // need to put it in the current linearized region. 2693*a06bfe05SJan Sjodin CurrentMerge = createIfRegion(CurrentMerge, MBB, LRegion, BBSelectRegIn, 2694*a06bfe05SJan Sjodin BBSelectRegOut); 2695*a06bfe05SJan Sjodin if (CurrentMerge) { 2696*a06bfe05SJan Sjodin TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 2697*a06bfe05SJan Sjodin } 2698*a06bfe05SJan Sjodin 2699*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2700*a06bfe05SJan Sjodin } 2701*a06bfe05SJan Sjodin } 2702*a06bfe05SJan Sjodin 2703*a06bfe05SJan Sjodin LRegion->removeFalseRegisterKills(MRI); 2704*a06bfe05SJan Sjodin 2705*a06bfe05SJan Sjodin if (LRegion->getHasLoop()) { 2706*a06bfe05SJan Sjodin MachineBasicBlock *NewSucc = splitEntry(LRegion); 2707*a06bfe05SJan Sjodin if (isFunctionEntryBlock(LRegion->getEntry())) { 2708*a06bfe05SJan Sjodin resolvePHIInfos(LRegion->getEntry()); 2709*a06bfe05SJan Sjodin } 2710*a06bfe05SJan Sjodin const DebugLoc &DL = NewSucc->findDebugLoc(NewSucc->getFirstNonPHI()); 2711*a06bfe05SJan Sjodin unsigned InReg = LRegion->getBBSelectRegIn(); 2712*a06bfe05SJan Sjodin unsigned InnerSelectReg = 2713*a06bfe05SJan Sjodin MRI->createVirtualRegister(MRI->getRegClass(InReg)); 2714*a06bfe05SJan Sjodin unsigned NewInReg = MRI->createVirtualRegister(MRI->getRegClass(InReg)); 2715*a06bfe05SJan Sjodin TII->materializeImmediate(*(LRegion->getEntry()), 2716*a06bfe05SJan Sjodin LRegion->getEntry()->getFirstTerminator(), DL, 2717*a06bfe05SJan Sjodin NewInReg, Region->getEntry()->getNumber()); 2718*a06bfe05SJan Sjodin // Need to be careful about updating the registers inside the region. 2719*a06bfe05SJan Sjodin LRegion->replaceRegisterInsideRegion(InReg, InnerSelectReg, false, MRI); 2720*a06bfe05SJan Sjodin DEBUG(dbgs() << "Loop BBSelect Merge PHI:\n"); 2721*a06bfe05SJan Sjodin insertMergePHI(LRegion->getEntry(), LRegion->getExit(), NewSucc, 2722*a06bfe05SJan Sjodin InnerSelectReg, NewInReg, 2723*a06bfe05SJan Sjodin LRegion->getRegionMRT()->getInnerOutputRegister()); 2724*a06bfe05SJan Sjodin splitExit(LRegion); 2725*a06bfe05SJan Sjodin TII->convertNonUniformLoopRegion(NewSucc, LastMerge); 2726*a06bfe05SJan Sjodin } 2727*a06bfe05SJan Sjodin 2728*a06bfe05SJan Sjodin if (Region->isRoot()) { 2729*a06bfe05SJan Sjodin TII->insertReturn(*LastMerge); 2730*a06bfe05SJan Sjodin } 2731*a06bfe05SJan Sjodin 2732*a06bfe05SJan Sjodin DEBUG(Region->getEntry()->getParent()->dump()); 2733*a06bfe05SJan Sjodin DEBUG(LRegion->print(dbgs(), TRI)); 2734*a06bfe05SJan Sjodin DEBUG(PHIInfo.dump(MRI)); 2735*a06bfe05SJan Sjodin 2736*a06bfe05SJan Sjodin DEBUG(dbgs() << "===========If Region End===============\n"); 2737*a06bfe05SJan Sjodin 2738*a06bfe05SJan Sjodin Region->setLinearizedRegion(LRegion); 2739*a06bfe05SJan Sjodin return true; 2740*a06bfe05SJan Sjodin } 2741*a06bfe05SJan Sjodin 2742*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::structurizeRegion(RegionMRT *Region) { 2743*a06bfe05SJan Sjodin if (false && regionIsSimpleIf(Region)) { 2744*a06bfe05SJan Sjodin transformSimpleIfRegion(Region); 2745*a06bfe05SJan Sjodin return true; 2746*a06bfe05SJan Sjodin } else if (regionIsSequence(Region)) { 2747*a06bfe05SJan Sjodin fixupRegionExits(Region); 2748*a06bfe05SJan Sjodin return false; 2749*a06bfe05SJan Sjodin } else { 2750*a06bfe05SJan Sjodin structurizeComplexRegion(Region); 2751*a06bfe05SJan Sjodin } 2752*a06bfe05SJan Sjodin return false; 2753*a06bfe05SJan Sjodin } 2754*a06bfe05SJan Sjodin 2755*a06bfe05SJan Sjodin static int structurize_once = 0; 2756*a06bfe05SJan Sjodin 2757*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::structurizeRegions(RegionMRT *Region, 2758*a06bfe05SJan Sjodin bool isTopRegion) { 2759*a06bfe05SJan Sjodin bool Changed = false; 2760*a06bfe05SJan Sjodin 2761*a06bfe05SJan Sjodin auto Children = Region->getChildren(); 2762*a06bfe05SJan Sjodin for (auto CI : *Children) { 2763*a06bfe05SJan Sjodin if (CI->isRegion()) { 2764*a06bfe05SJan Sjodin Changed |= structurizeRegions(CI->getRegionMRT(), false); 2765*a06bfe05SJan Sjodin } 2766*a06bfe05SJan Sjodin } 2767*a06bfe05SJan Sjodin 2768*a06bfe05SJan Sjodin if (structurize_once < 2 || true) { 2769*a06bfe05SJan Sjodin Changed |= structurizeRegion(Region); 2770*a06bfe05SJan Sjodin structurize_once++; 2771*a06bfe05SJan Sjodin } 2772*a06bfe05SJan Sjodin return Changed; 2773*a06bfe05SJan Sjodin } 2774*a06bfe05SJan Sjodin 2775*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::initFallthroughMap(MachineFunction &MF) { 2776*a06bfe05SJan Sjodin DEBUG(dbgs() << "Fallthrough Map:\n"); 2777*a06bfe05SJan Sjodin for (auto &MBBI : MF) { 2778*a06bfe05SJan Sjodin MachineBasicBlock *MBB = MBBI.getFallThrough(); 2779*a06bfe05SJan Sjodin if (MBB != nullptr) { 2780*a06bfe05SJan Sjodin DEBUG(dbgs() << "Fallthrough: " << MBBI.getNumber() << " -> " 2781*a06bfe05SJan Sjodin << MBB->getNumber() << "\n"); 2782*a06bfe05SJan Sjodin } 2783*a06bfe05SJan Sjodin FallthroughMap[&MBBI] = MBB; 2784*a06bfe05SJan Sjodin } 2785*a06bfe05SJan Sjodin } 2786*a06bfe05SJan Sjodin 2787*a06bfe05SJan Sjodin void AMDGPUMachineCFGStructurizer::createLinearizedRegion(RegionMRT *Region, 2788*a06bfe05SJan Sjodin unsigned SelectOut) { 2789*a06bfe05SJan Sjodin LinearizedRegion *LRegion = new LinearizedRegion(); 2790*a06bfe05SJan Sjodin if (SelectOut) { 2791*a06bfe05SJan Sjodin LRegion->addLiveOut(SelectOut); 2792*a06bfe05SJan Sjodin DEBUG(dbgs() << "Add LiveOut (BBSelect): " << PrintReg(SelectOut, TRI) 2793*a06bfe05SJan Sjodin << "\n"); 2794*a06bfe05SJan Sjodin } 2795*a06bfe05SJan Sjodin LRegion->setRegionMRT(Region); 2796*a06bfe05SJan Sjodin Region->setLinearizedRegion(LRegion); 2797*a06bfe05SJan Sjodin LRegion->setParent(Region->getParent() 2798*a06bfe05SJan Sjodin ? Region->getParent()->getLinearizedRegion() 2799*a06bfe05SJan Sjodin : nullptr); 2800*a06bfe05SJan Sjodin } 2801*a06bfe05SJan Sjodin 2802*a06bfe05SJan Sjodin unsigned 2803*a06bfe05SJan Sjodin AMDGPUMachineCFGStructurizer::initializeSelectRegisters(MRT *MRT, unsigned SelectOut, 2804*a06bfe05SJan Sjodin MachineRegisterInfo *MRI, 2805*a06bfe05SJan Sjodin const SIInstrInfo *TII) { 2806*a06bfe05SJan Sjodin if (MRT->isRegion()) { 2807*a06bfe05SJan Sjodin RegionMRT *Region = MRT->getRegionMRT(); 2808*a06bfe05SJan Sjodin Region->setBBSelectRegOut(SelectOut); 2809*a06bfe05SJan Sjodin unsigned InnerSelectOut = createBBSelectReg(TII, MRI); 2810*a06bfe05SJan Sjodin 2811*a06bfe05SJan Sjodin // Fixme: Move linearization creation to the original spot 2812*a06bfe05SJan Sjodin createLinearizedRegion(Region, SelectOut); 2813*a06bfe05SJan Sjodin 2814*a06bfe05SJan Sjodin for (auto CI = Region->getChildren()->begin(), 2815*a06bfe05SJan Sjodin CE = Region->getChildren()->end(); 2816*a06bfe05SJan Sjodin CI != CE; ++CI) { 2817*a06bfe05SJan Sjodin InnerSelectOut = 2818*a06bfe05SJan Sjodin initializeSelectRegisters((*CI), InnerSelectOut, MRI, TII); 2819*a06bfe05SJan Sjodin } 2820*a06bfe05SJan Sjodin MRT->setBBSelectRegIn(InnerSelectOut); 2821*a06bfe05SJan Sjodin return InnerSelectOut; 2822*a06bfe05SJan Sjodin } else { 2823*a06bfe05SJan Sjodin MRT->setBBSelectRegOut(SelectOut); 2824*a06bfe05SJan Sjodin unsigned NewSelectIn = createBBSelectReg(TII, MRI); 2825*a06bfe05SJan Sjodin MRT->setBBSelectRegIn(NewSelectIn); 2826*a06bfe05SJan Sjodin return NewSelectIn; 2827*a06bfe05SJan Sjodin } 2828*a06bfe05SJan Sjodin } 2829*a06bfe05SJan Sjodin 2830*a06bfe05SJan Sjodin static void checkRegOnlyPHIInputs(MachineFunction &MF) { 2831*a06bfe05SJan Sjodin for (auto &MBBI : MF) { 2832*a06bfe05SJan Sjodin for (MachineBasicBlock::instr_iterator I = MBBI.instr_begin(), 2833*a06bfe05SJan Sjodin E = MBBI.instr_end(); 2834*a06bfe05SJan Sjodin I != E; ++I) { 2835*a06bfe05SJan Sjodin MachineInstr &Instr = *I; 2836*a06bfe05SJan Sjodin if (Instr.isPHI()) { 2837*a06bfe05SJan Sjodin int numPreds = getPHINumInputs(Instr); 2838*a06bfe05SJan Sjodin for (int i = 0; i < numPreds; ++i) { 2839*a06bfe05SJan Sjodin assert(Instr.getOperand(i * 2 + 1).isReg() && 2840*a06bfe05SJan Sjodin "PHI Operand not a register"); 2841*a06bfe05SJan Sjodin } 2842*a06bfe05SJan Sjodin } 2843*a06bfe05SJan Sjodin } 2844*a06bfe05SJan Sjodin } 2845*a06bfe05SJan Sjodin } 2846*a06bfe05SJan Sjodin 2847*a06bfe05SJan Sjodin 2848*a06bfe05SJan Sjodin INITIALIZE_PASS_BEGIN(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 2849*a06bfe05SJan Sjodin "AMDGPU Machine CFG Structurizer", false, false) 2850*a06bfe05SJan Sjodin INITIALIZE_PASS_DEPENDENCY(MachineRegionInfoPass) 2851*a06bfe05SJan Sjodin INITIALIZE_PASS_END(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 2852*a06bfe05SJan Sjodin "AMDGPU Machine CFG Structurizer", false, false) 2853*a06bfe05SJan Sjodin 2854*a06bfe05SJan Sjodin char AMDGPUMachineCFGStructurizerID = AMDGPUMachineCFGStructurizer::ID; 2855*a06bfe05SJan Sjodin 2856*a06bfe05SJan Sjodin 2857*a06bfe05SJan Sjodin bool AMDGPUMachineCFGStructurizer::runOnMachineFunction(MachineFunction &MF) { 2858*a06bfe05SJan Sjodin const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 2859*a06bfe05SJan Sjodin const SIInstrInfo *TII = ST.getInstrInfo(); 2860*a06bfe05SJan Sjodin TRI = ST.getRegisterInfo(); 2861*a06bfe05SJan Sjodin MRI = &(MF.getRegInfo()); 2862*a06bfe05SJan Sjodin initFallthroughMap(MF); 2863*a06bfe05SJan Sjodin 2864*a06bfe05SJan Sjodin checkRegOnlyPHIInputs(MF); 2865*a06bfe05SJan Sjodin DEBUG(dbgs() << "----STRUCTURIZER START----\n"); 2866*a06bfe05SJan Sjodin DEBUG(MF.dump()); 2867*a06bfe05SJan Sjodin 2868*a06bfe05SJan Sjodin Regions = &(getAnalysis<MachineRegionInfoPass>().getRegionInfo()); 2869*a06bfe05SJan Sjodin DEBUG(Regions->dump()); 2870*a06bfe05SJan Sjodin 2871*a06bfe05SJan Sjodin RegionMRT *RTree = MRT::buildMRT(MF, Regions, TII, MRI); 2872*a06bfe05SJan Sjodin setRegionMRT(RTree); 2873*a06bfe05SJan Sjodin initializeSelectRegisters(RTree, 0, MRI, TII); 2874*a06bfe05SJan Sjodin DEBUG(RTree->dump(TRI)); 2875*a06bfe05SJan Sjodin bool result = structurizeRegions(RTree, true); 2876*a06bfe05SJan Sjodin delete RTree; 2877*a06bfe05SJan Sjodin DEBUG(dbgs() << "----STRUCTURIZER END----\n"); 2878*a06bfe05SJan Sjodin initFallthroughMap(MF); 2879*a06bfe05SJan Sjodin return result; 2880*a06bfe05SJan Sjodin } 2881*a06bfe05SJan Sjodin 2882*a06bfe05SJan Sjodin FunctionPass *llvm::createAMDGPUMachineCFGStructurizerPass() { 2883*a06bfe05SJan Sjodin return new AMDGPUMachineCFGStructurizer(); 2884*a06bfe05SJan Sjodin } 2885