10b57cec5SDimitry Andric //===- AMDGPUMachineCFGStructurizer.cpp - Machine code if conversion pass. ===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the machine instruction level CFG structurizer pass. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "AMDGPU.h" 14e8d8bef9SDimitry Andric #include "GCNSubtarget.h" 150b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 160b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegionInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 24480093f4SDimitry Andric #include "llvm/InitializePasses.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace llvm; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpucfgstructurizer" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class PHILinearizeDestIterator; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric class PHILinearize { 350b57cec5SDimitry Andric friend class PHILinearizeDestIterator; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric public: 380b57cec5SDimitry Andric using PHISourceT = std::pair<unsigned, MachineBasicBlock *>; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric private: 410b57cec5SDimitry Andric using PHISourcesT = DenseSet<PHISourceT>; 420b57cec5SDimitry Andric using PHIInfoElementT = struct { 430b57cec5SDimitry Andric unsigned DestReg; 440b57cec5SDimitry Andric DebugLoc DL; 450b57cec5SDimitry Andric PHISourcesT Sources; 460b57cec5SDimitry Andric }; 470b57cec5SDimitry Andric using PHIInfoT = SmallPtrSet<PHIInfoElementT *, 2>; 480b57cec5SDimitry Andric PHIInfoT PHIInfo; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric static unsigned phiInfoElementGetDest(PHIInfoElementT *Info); 510b57cec5SDimitry Andric static void phiInfoElementSetDef(PHIInfoElementT *Info, unsigned NewDef); 520b57cec5SDimitry Andric static PHISourcesT &phiInfoElementGetSources(PHIInfoElementT *Info); 530b57cec5SDimitry Andric static void phiInfoElementAddSource(PHIInfoElementT *Info, unsigned SourceReg, 540b57cec5SDimitry Andric MachineBasicBlock *SourceMBB); 550b57cec5SDimitry Andric static void phiInfoElementRemoveSource(PHIInfoElementT *Info, 560b57cec5SDimitry Andric unsigned SourceReg, 570b57cec5SDimitry Andric MachineBasicBlock *SourceMBB); 580b57cec5SDimitry Andric PHIInfoElementT *findPHIInfoElement(unsigned DestReg); 590b57cec5SDimitry Andric PHIInfoElementT *findPHIInfoElementFromSource(unsigned SourceReg, 600b57cec5SDimitry Andric MachineBasicBlock *SourceMBB); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric bool findSourcesFromMBB(MachineBasicBlock *SourceMBB, 640b57cec5SDimitry Andric SmallVector<unsigned, 4> &Sources); 650b57cec5SDimitry Andric void addDest(unsigned DestReg, const DebugLoc &DL); 660b57cec5SDimitry Andric void replaceDef(unsigned OldDestReg, unsigned NewDestReg); 670b57cec5SDimitry Andric void deleteDef(unsigned DestReg); 680b57cec5SDimitry Andric void addSource(unsigned DestReg, unsigned SourceReg, 690b57cec5SDimitry Andric MachineBasicBlock *SourceMBB); 700b57cec5SDimitry Andric void removeSource(unsigned DestReg, unsigned SourceReg, 710b57cec5SDimitry Andric MachineBasicBlock *SourceMBB = nullptr); 720b57cec5SDimitry Andric bool findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB, 730b57cec5SDimitry Andric unsigned &DestReg); 740b57cec5SDimitry Andric bool isSource(unsigned Reg, MachineBasicBlock *SourceMBB = nullptr); 750b57cec5SDimitry Andric unsigned getNumSources(unsigned DestReg); 760b57cec5SDimitry Andric void dump(MachineRegisterInfo *MRI); 770b57cec5SDimitry Andric void clear(); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric using source_iterator = PHISourcesT::iterator; 800b57cec5SDimitry Andric using dest_iterator = PHILinearizeDestIterator; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric dest_iterator dests_begin(); 830b57cec5SDimitry Andric dest_iterator dests_end(); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric source_iterator sources_begin(unsigned Reg); 860b57cec5SDimitry Andric source_iterator sources_end(unsigned Reg); 870b57cec5SDimitry Andric }; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric class PHILinearizeDestIterator { 900b57cec5SDimitry Andric private: 910b57cec5SDimitry Andric PHILinearize::PHIInfoT::iterator Iter; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric public: 940b57cec5SDimitry Andric PHILinearizeDestIterator(PHILinearize::PHIInfoT::iterator I) : Iter(I) {} 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric unsigned operator*() { return PHILinearize::phiInfoElementGetDest(*Iter); } 970b57cec5SDimitry Andric PHILinearizeDestIterator &operator++() { 980b57cec5SDimitry Andric ++Iter; 990b57cec5SDimitry Andric return *this; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric bool operator==(const PHILinearizeDestIterator &I) const { 1020b57cec5SDimitry Andric return I.Iter == Iter; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric bool operator!=(const PHILinearizeDestIterator &I) const { 1050b57cec5SDimitry Andric return I.Iter != Iter; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric }; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric } // end anonymous namespace 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric unsigned PHILinearize::phiInfoElementGetDest(PHIInfoElementT *Info) { 1120b57cec5SDimitry Andric return Info->DestReg; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void PHILinearize::phiInfoElementSetDef(PHIInfoElementT *Info, 1160b57cec5SDimitry Andric unsigned NewDef) { 1170b57cec5SDimitry Andric Info->DestReg = NewDef; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric PHILinearize::PHISourcesT & 1210b57cec5SDimitry Andric PHILinearize::phiInfoElementGetSources(PHIInfoElementT *Info) { 1220b57cec5SDimitry Andric return Info->Sources; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric void PHILinearize::phiInfoElementAddSource(PHIInfoElementT *Info, 1260b57cec5SDimitry Andric unsigned SourceReg, 1270b57cec5SDimitry Andric MachineBasicBlock *SourceMBB) { 1280b57cec5SDimitry Andric // Assertion ensures we don't use the same SourceMBB for the 1290b57cec5SDimitry Andric // sources, because we cannot have different registers with 1300b57cec5SDimitry Andric // identical predecessors, but we can have the same register for 1310b57cec5SDimitry Andric // multiple predecessors. 1320b57cec5SDimitry Andric #if !defined(NDEBUG) 1330b57cec5SDimitry Andric for (auto SI : phiInfoElementGetSources(Info)) { 1340b57cec5SDimitry Andric assert((SI.second != SourceMBB || SourceReg == SI.first)); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric #endif 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric phiInfoElementGetSources(Info).insert(PHISourceT(SourceReg, SourceMBB)); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric void PHILinearize::phiInfoElementRemoveSource(PHIInfoElementT *Info, 1420b57cec5SDimitry Andric unsigned SourceReg, 1430b57cec5SDimitry Andric MachineBasicBlock *SourceMBB) { 1440b57cec5SDimitry Andric auto &Sources = phiInfoElementGetSources(Info); 1450b57cec5SDimitry Andric SmallVector<PHISourceT, 4> ElimiatedSources; 1460b57cec5SDimitry Andric for (auto SI : Sources) { 1470b57cec5SDimitry Andric if (SI.first == SourceReg && 1480b57cec5SDimitry Andric (SI.second == nullptr || SI.second == SourceMBB)) { 1490b57cec5SDimitry Andric ElimiatedSources.push_back(PHISourceT(SI.first, SI.second)); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric for (auto &Source : ElimiatedSources) { 1540b57cec5SDimitry Andric Sources.erase(Source); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric PHILinearize::PHIInfoElementT * 1590b57cec5SDimitry Andric PHILinearize::findPHIInfoElement(unsigned DestReg) { 160bdd1243dSDimitry Andric for (auto *I : PHIInfo) { 1610b57cec5SDimitry Andric if (phiInfoElementGetDest(I) == DestReg) { 1620b57cec5SDimitry Andric return I; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric return nullptr; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric PHILinearize::PHIInfoElementT * 1690b57cec5SDimitry Andric PHILinearize::findPHIInfoElementFromSource(unsigned SourceReg, 1700b57cec5SDimitry Andric MachineBasicBlock *SourceMBB) { 171bdd1243dSDimitry Andric for (auto *I : PHIInfo) { 1720b57cec5SDimitry Andric for (auto SI : phiInfoElementGetSources(I)) { 1730b57cec5SDimitry Andric if (SI.first == SourceReg && 1740b57cec5SDimitry Andric (SI.second == nullptr || SI.second == SourceMBB)) { 1750b57cec5SDimitry Andric return I; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric return nullptr; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric bool PHILinearize::findSourcesFromMBB(MachineBasicBlock *SourceMBB, 1830b57cec5SDimitry Andric SmallVector<unsigned, 4> &Sources) { 1840b57cec5SDimitry Andric bool FoundSource = false; 185bdd1243dSDimitry Andric for (auto *I : PHIInfo) { 1860b57cec5SDimitry Andric for (auto SI : phiInfoElementGetSources(I)) { 1870b57cec5SDimitry Andric if (SI.second == SourceMBB) { 1880b57cec5SDimitry Andric FoundSource = true; 1890b57cec5SDimitry Andric Sources.push_back(SI.first); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric return FoundSource; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric void PHILinearize::addDest(unsigned DestReg, const DebugLoc &DL) { 197349cc55cSDimitry Andric assert(findPHIInfoElement(DestReg) == nullptr && "Dest already exists"); 1980b57cec5SDimitry Andric PHISourcesT EmptySet; 1990b57cec5SDimitry Andric PHIInfoElementT *NewElement = new PHIInfoElementT(); 2000b57cec5SDimitry Andric NewElement->DestReg = DestReg; 2010b57cec5SDimitry Andric NewElement->DL = DL; 2020b57cec5SDimitry Andric NewElement->Sources = EmptySet; 2030b57cec5SDimitry Andric PHIInfo.insert(NewElement); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void PHILinearize::replaceDef(unsigned OldDestReg, unsigned NewDestReg) { 2070b57cec5SDimitry Andric phiInfoElementSetDef(findPHIInfoElement(OldDestReg), NewDestReg); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric void PHILinearize::deleteDef(unsigned DestReg) { 2110b57cec5SDimitry Andric PHIInfoElementT *InfoElement = findPHIInfoElement(DestReg); 2120b57cec5SDimitry Andric PHIInfo.erase(InfoElement); 2130b57cec5SDimitry Andric delete InfoElement; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric void PHILinearize::addSource(unsigned DestReg, unsigned SourceReg, 2170b57cec5SDimitry Andric MachineBasicBlock *SourceMBB) { 2180b57cec5SDimitry Andric phiInfoElementAddSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric void PHILinearize::removeSource(unsigned DestReg, unsigned SourceReg, 2220b57cec5SDimitry Andric MachineBasicBlock *SourceMBB) { 2230b57cec5SDimitry Andric phiInfoElementRemoveSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric bool PHILinearize::findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB, 2270b57cec5SDimitry Andric unsigned &DestReg) { 2280b57cec5SDimitry Andric PHIInfoElementT *InfoElement = 2290b57cec5SDimitry Andric findPHIInfoElementFromSource(SourceReg, SourceMBB); 2300b57cec5SDimitry Andric if (InfoElement != nullptr) { 2310b57cec5SDimitry Andric DestReg = phiInfoElementGetDest(InfoElement); 2320b57cec5SDimitry Andric return true; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric return false; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric bool PHILinearize::isSource(unsigned Reg, MachineBasicBlock *SourceMBB) { 2380b57cec5SDimitry Andric unsigned DestReg; 2390b57cec5SDimitry Andric return findDest(Reg, SourceMBB, DestReg); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric unsigned PHILinearize::getNumSources(unsigned DestReg) { 2430b57cec5SDimitry Andric return phiInfoElementGetSources(findPHIInfoElement(DestReg)).size(); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2470b57cec5SDimitry Andric LLVM_DUMP_METHOD void PHILinearize::dump(MachineRegisterInfo *MRI) { 2480b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); 2490b57cec5SDimitry Andric dbgs() << "=PHIInfo Start=\n"; 250bdd1243dSDimitry Andric for (auto *PII : this->PHIInfo) { 2510b57cec5SDimitry Andric PHIInfoElementT &Element = *PII; 2520b57cec5SDimitry Andric dbgs() << "Dest: " << printReg(Element.DestReg, TRI) 2530b57cec5SDimitry Andric << " Sources: {"; 2540b57cec5SDimitry Andric for (auto &SI : Element.Sources) { 2550b57cec5SDimitry Andric dbgs() << printReg(SI.first, TRI) << '(' << printMBBReference(*SI.second) 2560b57cec5SDimitry Andric << "),"; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric dbgs() << "}\n"; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric dbgs() << "=PHIInfo End=\n"; 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric #endif 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric void PHILinearize::clear() { PHIInfo = PHIInfoT(); } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric PHILinearize::dest_iterator PHILinearize::dests_begin() { 2670b57cec5SDimitry Andric return PHILinearizeDestIterator(PHIInfo.begin()); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric PHILinearize::dest_iterator PHILinearize::dests_end() { 2710b57cec5SDimitry Andric return PHILinearizeDestIterator(PHIInfo.end()); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric PHILinearize::source_iterator PHILinearize::sources_begin(unsigned Reg) { 2750b57cec5SDimitry Andric auto InfoElement = findPHIInfoElement(Reg); 2760b57cec5SDimitry Andric return phiInfoElementGetSources(InfoElement).begin(); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric PHILinearize::source_iterator PHILinearize::sources_end(unsigned Reg) { 2800b57cec5SDimitry Andric auto InfoElement = findPHIInfoElement(Reg); 2810b57cec5SDimitry Andric return phiInfoElementGetSources(InfoElement).end(); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric static unsigned getPHINumInputs(MachineInstr &PHI) { 2850b57cec5SDimitry Andric assert(PHI.isPHI()); 2860b57cec5SDimitry Andric return (PHI.getNumOperands() - 1) / 2; 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric static MachineBasicBlock *getPHIPred(MachineInstr &PHI, unsigned Index) { 2900b57cec5SDimitry Andric assert(PHI.isPHI()); 2910b57cec5SDimitry Andric return PHI.getOperand(Index * 2 + 2).getMBB(); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric static void setPhiPred(MachineInstr &PHI, unsigned Index, 2950b57cec5SDimitry Andric MachineBasicBlock *NewPred) { 2960b57cec5SDimitry Andric PHI.getOperand(Index * 2 + 2).setMBB(NewPred); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric static unsigned getPHISourceReg(MachineInstr &PHI, unsigned Index) { 3000b57cec5SDimitry Andric assert(PHI.isPHI()); 3010b57cec5SDimitry Andric return PHI.getOperand(Index * 2 + 1).getReg(); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric static unsigned getPHIDestReg(MachineInstr &PHI) { 3050b57cec5SDimitry Andric assert(PHI.isPHI()); 3060b57cec5SDimitry Andric return PHI.getOperand(0).getReg(); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric namespace { 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric class RegionMRT; 3120b57cec5SDimitry Andric class MBBMRT; 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric class LinearizedRegion { 3150b57cec5SDimitry Andric protected: 3160b57cec5SDimitry Andric MachineBasicBlock *Entry; 3170b57cec5SDimitry Andric // The exit block is part of the region, and is the last 3180b57cec5SDimitry Andric // merge block before exiting the region. 3190b57cec5SDimitry Andric MachineBasicBlock *Exit; 3200b57cec5SDimitry Andric DenseSet<unsigned> LiveOuts; 3210b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 1> MBBs; 3220b57cec5SDimitry Andric bool HasLoop; 3230b57cec5SDimitry Andric LinearizedRegion *Parent; 3240b57cec5SDimitry Andric RegionMRT *RMRT; 3250b57cec5SDimitry Andric 326e8d8bef9SDimitry Andric void storeLiveOutReg(MachineBasicBlock *MBB, Register Reg, 3270b57cec5SDimitry Andric MachineInstr *DefInstr, const MachineRegisterInfo *MRI, 3280b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 3290b57cec5SDimitry Andric 330e8d8bef9SDimitry Andric void storeLiveOutRegRegion(RegionMRT *Region, Register Reg, 3310b57cec5SDimitry Andric MachineInstr *DefInstr, 3320b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 3330b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 3340b57cec5SDimitry Andric PHILinearize &PHIInfo); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric void storeMBBLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 3370b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo, 3380b57cec5SDimitry Andric RegionMRT *TopRegion); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric void storeLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 3410b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void storeLiveOuts(RegionMRT *Region, const MachineRegisterInfo *MRI, 3440b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo, 3450b57cec5SDimitry Andric RegionMRT *TopRegion = nullptr); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric public: 3480b57cec5SDimitry Andric LinearizedRegion(); 3490b57cec5SDimitry Andric LinearizedRegion(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI, 3500b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 3510b57cec5SDimitry Andric ~LinearizedRegion() = default; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric void setRegionMRT(RegionMRT *Region) { RMRT = Region; } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric RegionMRT *getRegionMRT() { return RMRT; } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric void setParent(LinearizedRegion *P) { Parent = P; } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric LinearizedRegion *getParent() { return Parent; } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric void setBBSelectRegIn(unsigned Reg); 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric unsigned getBBSelectRegIn(); 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric void setBBSelectRegOut(unsigned Reg, bool IsLiveOut); 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric unsigned getBBSelectRegOut(); 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric void setHasLoop(bool Value); 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric bool getHasLoop(); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric void addLiveOut(unsigned VReg); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void removeLiveOut(unsigned Reg); 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric void replaceLiveOut(unsigned OldReg, unsigned NewReg); 3800b57cec5SDimitry Andric 381e8d8bef9SDimitry Andric void replaceRegister(unsigned Register, class Register NewRegister, 3820b57cec5SDimitry Andric MachineRegisterInfo *MRI, bool ReplaceInside, 3830b57cec5SDimitry Andric bool ReplaceOutside, bool IncludeLoopPHIs); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric void replaceRegisterInsideRegion(unsigned Register, unsigned NewRegister, 3860b57cec5SDimitry Andric bool IncludeLoopPHIs, 3870b57cec5SDimitry Andric MachineRegisterInfo *MRI); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void replaceRegisterOutsideRegion(unsigned Register, unsigned NewRegister, 3900b57cec5SDimitry Andric bool IncludeLoopPHIs, 3910b57cec5SDimitry Andric MachineRegisterInfo *MRI); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric DenseSet<unsigned> *getLiveOuts(); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric void setEntry(MachineBasicBlock *NewEntry); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric MachineBasicBlock *getEntry(); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric void setExit(MachineBasicBlock *NewExit); 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric MachineBasicBlock *getExit(); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric void addMBB(MachineBasicBlock *MBB); 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric void addMBBs(LinearizedRegion *InnerRegion); 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric bool contains(MachineBasicBlock *MBB); 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric bool isLiveOut(unsigned Reg); 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric bool hasNoDef(unsigned Reg, MachineRegisterInfo *MRI); 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric void removeFalseRegisterKills(MachineRegisterInfo *MRI); 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric void initLiveOut(RegionMRT *Region, const MachineRegisterInfo *MRI, 4160b57cec5SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo); 4170b57cec5SDimitry Andric }; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric class MRT { 4200b57cec5SDimitry Andric protected: 4210b57cec5SDimitry Andric RegionMRT *Parent; 4220b57cec5SDimitry Andric unsigned BBSelectRegIn; 4230b57cec5SDimitry Andric unsigned BBSelectRegOut; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric public: 4260b57cec5SDimitry Andric virtual ~MRT() = default; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric unsigned getBBSelectRegIn() { return BBSelectRegIn; } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric unsigned getBBSelectRegOut() { return BBSelectRegOut; } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric void setBBSelectRegIn(unsigned Reg) { BBSelectRegIn = Reg; } 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric void setBBSelectRegOut(unsigned Reg) { BBSelectRegOut = Reg; } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric virtual RegionMRT *getRegionMRT() { return nullptr; } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric virtual MBBMRT *getMBBMRT() { return nullptr; } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric bool isRegion() { return getRegionMRT() != nullptr; } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric bool isMBB() { return getMBBMRT() != nullptr; } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric bool isRoot() { return Parent == nullptr; } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric void setParent(RegionMRT *Region) { Parent = Region; } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric RegionMRT *getParent() { return Parent; } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric static MachineBasicBlock * 4510b57cec5SDimitry Andric initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo, 4520b57cec5SDimitry Andric DenseMap<MachineRegion *, RegionMRT *> &RegionMap); 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric static RegionMRT *buildMRT(MachineFunction &MF, 4550b57cec5SDimitry Andric const MachineRegionInfo *RegionInfo, 4560b57cec5SDimitry Andric const SIInstrInfo *TII, 4570b57cec5SDimitry Andric MachineRegisterInfo *MRI); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric virtual void dump(const TargetRegisterInfo *TRI, int depth = 0) = 0; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric void dumpDepth(int depth) { 4620b57cec5SDimitry Andric for (int i = depth; i > 0; --i) { 4630b57cec5SDimitry Andric dbgs() << " "; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric }; 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric class MBBMRT : public MRT { 4690b57cec5SDimitry Andric MachineBasicBlock *MBB; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric public: 4720b57cec5SDimitry Andric MBBMRT(MachineBasicBlock *BB) : MBB(BB) { 4730b57cec5SDimitry Andric setParent(nullptr); 4740b57cec5SDimitry Andric setBBSelectRegOut(0); 4750b57cec5SDimitry Andric setBBSelectRegIn(0); 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric MBBMRT *getMBBMRT() override { return this; } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric MachineBasicBlock *getMBB() { return MBB; } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric void dump(const TargetRegisterInfo *TRI, int depth = 0) override { 4830b57cec5SDimitry Andric dumpDepth(depth); 4840b57cec5SDimitry Andric dbgs() << "MBB: " << getMBB()->getNumber(); 4850b57cec5SDimitry Andric dbgs() << " In: " << printReg(getBBSelectRegIn(), TRI); 4860b57cec5SDimitry Andric dbgs() << ", Out: " << printReg(getBBSelectRegOut(), TRI) << "\n"; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric }; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric class RegionMRT : public MRT { 4910b57cec5SDimitry Andric protected: 4920b57cec5SDimitry Andric MachineRegion *Region; 4930b57cec5SDimitry Andric LinearizedRegion *LRegion = nullptr; 4940b57cec5SDimitry Andric MachineBasicBlock *Succ = nullptr; 4950b57cec5SDimitry Andric SetVector<MRT *> Children; 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric public: 4980b57cec5SDimitry Andric RegionMRT(MachineRegion *MachineRegion) : Region(MachineRegion) { 4990b57cec5SDimitry Andric setParent(nullptr); 5000b57cec5SDimitry Andric setBBSelectRegOut(0); 5010b57cec5SDimitry Andric setBBSelectRegIn(0); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric ~RegionMRT() override { 5050b57cec5SDimitry Andric if (LRegion) { 5060b57cec5SDimitry Andric delete LRegion; 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 509bdd1243dSDimitry Andric for (auto *CI : Children) { 5100b57cec5SDimitry Andric delete &(*CI); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric RegionMRT *getRegionMRT() override { return this; } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric void setLinearizedRegion(LinearizedRegion *LinearizeRegion) { 5170b57cec5SDimitry Andric LRegion = LinearizeRegion; 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric LinearizedRegion *getLinearizedRegion() { return LRegion; } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric MachineRegion *getMachineRegion() { return Region; } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric unsigned getInnerOutputRegister() { 5250b57cec5SDimitry Andric return (*(Children.begin()))->getBBSelectRegOut(); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric void addChild(MRT *Tree) { Children.insert(Tree); } 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric SetVector<MRT *> *getChildren() { return &Children; } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric void dump(const TargetRegisterInfo *TRI, int depth = 0) override { 5330b57cec5SDimitry Andric dumpDepth(depth); 5340b57cec5SDimitry Andric dbgs() << "Region: " << (void *)Region; 5350b57cec5SDimitry Andric dbgs() << " In: " << printReg(getBBSelectRegIn(), TRI); 5360b57cec5SDimitry Andric dbgs() << ", Out: " << printReg(getBBSelectRegOut(), TRI) << "\n"; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric dumpDepth(depth); 5390b57cec5SDimitry Andric if (getSucc()) 5400b57cec5SDimitry Andric dbgs() << "Succ: " << getSucc()->getNumber() << "\n"; 5410b57cec5SDimitry Andric else 5420b57cec5SDimitry Andric dbgs() << "Succ: none \n"; 543bdd1243dSDimitry Andric for (auto *MRTI : Children) { 5440b57cec5SDimitry Andric MRTI->dump(TRI, depth + 1); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric MRT *getEntryTree() { return Children.back(); } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric MRT *getExitTree() { return Children.front(); } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric MachineBasicBlock *getEntry() { 5530b57cec5SDimitry Andric MRT *Tree = Children.back(); 5540b57cec5SDimitry Andric return (Tree->isRegion()) ? Tree->getRegionMRT()->getEntry() 5550b57cec5SDimitry Andric : Tree->getMBBMRT()->getMBB(); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric MachineBasicBlock *getExit() { 5590b57cec5SDimitry Andric MRT *Tree = Children.front(); 5600b57cec5SDimitry Andric return (Tree->isRegion()) ? Tree->getRegionMRT()->getExit() 5610b57cec5SDimitry Andric : Tree->getMBBMRT()->getMBB(); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric void setSucc(MachineBasicBlock *MBB) { Succ = MBB; } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric MachineBasicBlock *getSucc() { return Succ; } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric bool contains(MachineBasicBlock *MBB) { 569bdd1243dSDimitry Andric for (auto *CI : Children) { 5700b57cec5SDimitry Andric if (CI->isMBB()) { 571*0fca6ea1SDimitry Andric if (MBB == CI->getMBBMRT()->getMBB()) 5720b57cec5SDimitry Andric return true; 5730b57cec5SDimitry Andric } else { 574*0fca6ea1SDimitry Andric if (CI->getRegionMRT()->contains(MBB)) 5750b57cec5SDimitry Andric return true; 576*0fca6ea1SDimitry Andric if (CI->getRegionMRT()->getLinearizedRegion() != nullptr && 577*0fca6ea1SDimitry Andric CI->getRegionMRT()->getLinearizedRegion()->contains(MBB)) 5780b57cec5SDimitry Andric return true; 5790b57cec5SDimitry Andric } 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric return false; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void replaceLiveOutReg(unsigned Register, unsigned NewRegister) { 5850b57cec5SDimitry Andric LinearizedRegion *LRegion = getLinearizedRegion(); 5860b57cec5SDimitry Andric LRegion->replaceLiveOut(Register, NewRegister); 5870b57cec5SDimitry Andric for (auto &CI : Children) { 5880b57cec5SDimitry Andric if (CI->isRegion()) { 5890b57cec5SDimitry Andric CI->getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric }; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric } // end anonymous namespace 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric static unsigned createBBSelectReg(const SIInstrInfo *TII, 5980b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 5990b57cec5SDimitry Andric return MRI->createVirtualRegister(TII->getPreferredSelectRegClass(32)); 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric MachineBasicBlock * 6030b57cec5SDimitry Andric MRT::initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo, 6040b57cec5SDimitry Andric DenseMap<MachineRegion *, RegionMRT *> &RegionMap) { 6050b57cec5SDimitry Andric for (auto &MFI : MF) { 6060b57cec5SDimitry Andric MachineBasicBlock *ExitMBB = &MFI; 607349cc55cSDimitry Andric if (ExitMBB->succ_empty()) { 6080b57cec5SDimitry Andric return ExitMBB; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric llvm_unreachable("CFG has no exit block"); 6120b57cec5SDimitry Andric return nullptr; 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric RegionMRT *MRT::buildMRT(MachineFunction &MF, 6160b57cec5SDimitry Andric const MachineRegionInfo *RegionInfo, 6170b57cec5SDimitry Andric const SIInstrInfo *TII, MachineRegisterInfo *MRI) { 6180b57cec5SDimitry Andric SmallPtrSet<MachineRegion *, 4> PlacedRegions; 6190b57cec5SDimitry Andric DenseMap<MachineRegion *, RegionMRT *> RegionMap; 6200b57cec5SDimitry Andric MachineRegion *TopLevelRegion = RegionInfo->getTopLevelRegion(); 6210b57cec5SDimitry Andric RegionMRT *Result = new RegionMRT(TopLevelRegion); 6220b57cec5SDimitry Andric RegionMap[TopLevelRegion] = Result; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric // Insert the exit block first, we need it to be the merge node 6250b57cec5SDimitry Andric // for the top level region. 6260b57cec5SDimitry Andric MachineBasicBlock *Exit = initializeMRT(MF, RegionInfo, RegionMap); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric unsigned BBSelectRegIn = createBBSelectReg(TII, MRI); 6290b57cec5SDimitry Andric MBBMRT *ExitMRT = new MBBMRT(Exit); 6300b57cec5SDimitry Andric RegionMap[RegionInfo->getRegionFor(Exit)]->addChild(ExitMRT); 6310b57cec5SDimitry Andric ExitMRT->setBBSelectRegIn(BBSelectRegIn); 6320b57cec5SDimitry Andric 633bdd1243dSDimitry Andric for (auto *MBBI : post_order(&(MF.front()))) { 6340b57cec5SDimitry Andric MachineBasicBlock *MBB = &(*MBBI); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric // Skip Exit since we already added it 6370b57cec5SDimitry Andric if (MBB == Exit) { 6380b57cec5SDimitry Andric continue; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting " << printMBBReference(*MBB) << "\n"); 6420b57cec5SDimitry Andric MBBMRT *NewMBB = new MBBMRT(MBB); 6430b57cec5SDimitry Andric MachineRegion *Region = RegionInfo->getRegionFor(MBB); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric // Ensure we have the MRT region 6460b57cec5SDimitry Andric if (RegionMap.count(Region) == 0) { 6470b57cec5SDimitry Andric RegionMRT *NewMRTRegion = new RegionMRT(Region); 6480b57cec5SDimitry Andric RegionMap[Region] = NewMRTRegion; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric // Ensure all parents are in the RegionMap 6510b57cec5SDimitry Andric MachineRegion *Parent = Region->getParent(); 6520b57cec5SDimitry Andric while (RegionMap.count(Parent) == 0) { 6530b57cec5SDimitry Andric RegionMRT *NewMRTParent = new RegionMRT(Parent); 6540b57cec5SDimitry Andric NewMRTParent->addChild(NewMRTRegion); 6550b57cec5SDimitry Andric NewMRTRegion->setParent(NewMRTParent); 6560b57cec5SDimitry Andric RegionMap[Parent] = NewMRTParent; 6570b57cec5SDimitry Andric NewMRTRegion = NewMRTParent; 6580b57cec5SDimitry Andric Parent = Parent->getParent(); 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric RegionMap[Parent]->addChild(NewMRTRegion); 6610b57cec5SDimitry Andric NewMRTRegion->setParent(RegionMap[Parent]); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric // Add MBB to Region MRT 6650b57cec5SDimitry Andric RegionMap[Region]->addChild(NewMBB); 6660b57cec5SDimitry Andric NewMBB->setParent(RegionMap[Region]); 6670b57cec5SDimitry Andric RegionMap[Region]->setSucc(Region->getExit()); 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric return Result; 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 672e8d8bef9SDimitry Andric void LinearizedRegion::storeLiveOutReg(MachineBasicBlock *MBB, Register Reg, 6730b57cec5SDimitry Andric MachineInstr *DefInstr, 6740b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 6750b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 6760b57cec5SDimitry Andric PHILinearize &PHIInfo) { 677e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 6780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI) 6790b57cec5SDimitry Andric << "\n"); 6800b57cec5SDimitry Andric // If this is a source register to a PHI we are chaining, it 6810b57cec5SDimitry Andric // must be live out. 6820b57cec5SDimitry Andric if (PHIInfo.isSource(Reg)) { 6830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (PHI): " << printReg(Reg, TRI) << "\n"); 6840b57cec5SDimitry Andric addLiveOut(Reg); 6850b57cec5SDimitry Andric } else { 6860b57cec5SDimitry Andric // If this is live out of the MBB 6870b57cec5SDimitry Andric for (auto &UI : MRI->use_operands(Reg)) { 6880b57cec5SDimitry Andric if (UI.getParent()->getParent() != MBB) { 6890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (MBB " << printMBBReference(*MBB) 6900b57cec5SDimitry Andric << "): " << printReg(Reg, TRI) << "\n"); 6910b57cec5SDimitry Andric addLiveOut(Reg); 6920b57cec5SDimitry Andric } else { 6930b57cec5SDimitry Andric // If the use is in the same MBB we have to make sure 6940b57cec5SDimitry Andric // it is after the def, otherwise it is live out in a loop 6950b57cec5SDimitry Andric MachineInstr *UseInstr = UI.getParent(); 6960b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator 6970b57cec5SDimitry Andric MII = UseInstr->getIterator(), 6980b57cec5SDimitry Andric MIE = UseInstr->getParent()->instr_end(); 6990b57cec5SDimitry Andric MII != MIE; ++MII) { 7000b57cec5SDimitry Andric if ((&(*MII)) == DefInstr) { 7010b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Loop): " << printReg(Reg, TRI) 7020b57cec5SDimitry Andric << "\n"); 7030b57cec5SDimitry Andric addLiveOut(Reg); 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 712e8d8bef9SDimitry Andric void LinearizedRegion::storeLiveOutRegRegion(RegionMRT *Region, Register Reg, 7130b57cec5SDimitry Andric MachineInstr *DefInstr, 7140b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7150b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7160b57cec5SDimitry Andric PHILinearize &PHIInfo) { 717e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 7180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI) 7190b57cec5SDimitry Andric << "\n"); 7200b57cec5SDimitry Andric for (auto &UI : MRI->use_operands(Reg)) { 7210b57cec5SDimitry Andric if (!Region->contains(UI.getParent()->getParent())) { 7220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Region " << (void *)Region 7230b57cec5SDimitry Andric << "): " << printReg(Reg, TRI) << "\n"); 7240b57cec5SDimitry Andric addLiveOut(Reg); 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric void LinearizedRegion::storeLiveOuts(MachineBasicBlock *MBB, 7310b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7320b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7330b57cec5SDimitry Andric PHILinearize &PHIInfo) { 7340b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Begin (" << printMBBReference(*MBB) 7350b57cec5SDimitry Andric << ")-\n"); 7360b57cec5SDimitry Andric for (auto &II : *MBB) { 7370b57cec5SDimitry Andric for (auto &RI : II.defs()) { 7380b57cec5SDimitry Andric storeLiveOutReg(MBB, RI.getReg(), RI.getParent(), MRI, TRI, PHIInfo); 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric for (auto &IRI : II.implicit_operands()) { 7410b57cec5SDimitry Andric if (IRI.isDef()) { 7420b57cec5SDimitry Andric storeLiveOutReg(MBB, IRI.getReg(), IRI.getParent(), MRI, TRI, PHIInfo); 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // If we have a successor with a PHI, source coming from this MBB we have to 7480b57cec5SDimitry Andric // add the register as live out 749349cc55cSDimitry Andric for (MachineBasicBlock *Succ : MBB->successors()) { 750349cc55cSDimitry Andric for (auto &II : *Succ) { 7510b57cec5SDimitry Andric if (II.isPHI()) { 7520b57cec5SDimitry Andric MachineInstr &PHI = II; 7530b57cec5SDimitry Andric int numPreds = getPHINumInputs(PHI); 7540b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 7550b57cec5SDimitry Andric if (getPHIPred(PHI, i) == MBB) { 7560b57cec5SDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i); 7570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 7580b57cec5SDimitry Andric << "Add LiveOut (PhiSource " << printMBBReference(*MBB) 759349cc55cSDimitry Andric << " -> " << printMBBReference(*Succ) 7600b57cec5SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n"); 7610b57cec5SDimitry Andric addLiveOut(PHIReg); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Endn-\n"); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric void LinearizedRegion::storeMBBLiveOuts(MachineBasicBlock *MBB, 7720b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7730b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7740b57cec5SDimitry Andric PHILinearize &PHIInfo, 7750b57cec5SDimitry Andric RegionMRT *TopRegion) { 7760b57cec5SDimitry Andric for (auto &II : *MBB) { 7770b57cec5SDimitry Andric for (auto &RI : II.defs()) { 7780b57cec5SDimitry Andric storeLiveOutRegRegion(TopRegion, RI.getReg(), RI.getParent(), MRI, TRI, 7790b57cec5SDimitry Andric PHIInfo); 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric for (auto &IRI : II.implicit_operands()) { 7820b57cec5SDimitry Andric if (IRI.isDef()) { 7830b57cec5SDimitry Andric storeLiveOutRegRegion(TopRegion, IRI.getReg(), IRI.getParent(), MRI, 7840b57cec5SDimitry Andric TRI, PHIInfo); 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric void LinearizedRegion::storeLiveOuts(RegionMRT *Region, 7910b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7920b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7930b57cec5SDimitry Andric PHILinearize &PHIInfo, 7940b57cec5SDimitry Andric RegionMRT *CurrentTopRegion) { 7950b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getSucc(); 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric RegionMRT *TopRegion = 7980b57cec5SDimitry Andric CurrentTopRegion == nullptr ? Region : CurrentTopRegion; 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric // Check if exit is end of function, if so, no live outs. 8010b57cec5SDimitry Andric if (Exit == nullptr) 8020b57cec5SDimitry Andric return; 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric auto Children = Region->getChildren(); 805bdd1243dSDimitry Andric for (auto *CI : *Children) { 8060b57cec5SDimitry Andric if (CI->isMBB()) { 8070b57cec5SDimitry Andric auto MBB = CI->getMBBMRT()->getMBB(); 8080b57cec5SDimitry Andric storeMBBLiveOuts(MBB, MRI, TRI, PHIInfo, TopRegion); 8090b57cec5SDimitry Andric } else { 8100b57cec5SDimitry Andric LinearizedRegion *SubRegion = CI->getRegionMRT()->getLinearizedRegion(); 8110b57cec5SDimitry Andric // We should be limited to only store registers that are live out from the 812349cc55cSDimitry Andric // linearized region 813bdd1243dSDimitry Andric for (auto *MBBI : SubRegion->MBBs) { 8140b57cec5SDimitry Andric storeMBBLiveOuts(MBBI, MRI, TRI, PHIInfo, TopRegion); 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric if (CurrentTopRegion == nullptr) { 8200b57cec5SDimitry Andric auto Succ = Region->getSucc(); 8210b57cec5SDimitry Andric for (auto &II : *Succ) { 8220b57cec5SDimitry Andric if (II.isPHI()) { 8230b57cec5SDimitry Andric MachineInstr &PHI = II; 8240b57cec5SDimitry Andric int numPreds = getPHINumInputs(PHI); 8250b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 8260b57cec5SDimitry Andric if (Region->contains(getPHIPred(PHI, i))) { 8270b57cec5SDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i); 8280b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add Region LiveOut (" << (void *)Region 8290b57cec5SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n"); 8300b57cec5SDimitry Andric addLiveOut(PHIReg); 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric #ifndef NDEBUG 8390b57cec5SDimitry Andric void LinearizedRegion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { 8400b57cec5SDimitry Andric OS << "Linearized Region {"; 8410b57cec5SDimitry Andric bool IsFirst = true; 842bdd1243dSDimitry Andric for (auto *MBB : MBBs) { 8430b57cec5SDimitry Andric if (IsFirst) { 8440b57cec5SDimitry Andric IsFirst = false; 8450b57cec5SDimitry Andric } else { 8460b57cec5SDimitry Andric OS << " ,"; 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric OS << MBB->getNumber(); 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric OS << "} (" << Entry->getNumber() << ", " 8510b57cec5SDimitry Andric << (Exit == nullptr ? -1 : Exit->getNumber()) 8520b57cec5SDimitry Andric << "): In:" << printReg(getBBSelectRegIn(), TRI) 8530b57cec5SDimitry Andric << " Out:" << printReg(getBBSelectRegOut(), TRI) << " {"; 8540b57cec5SDimitry Andric for (auto &LI : LiveOuts) { 8550b57cec5SDimitry Andric OS << printReg(LI, TRI) << " "; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric OS << "} \n"; 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric #endif 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric unsigned LinearizedRegion::getBBSelectRegIn() { 8620b57cec5SDimitry Andric return getRegionMRT()->getBBSelectRegIn(); 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric unsigned LinearizedRegion::getBBSelectRegOut() { 8660b57cec5SDimitry Andric return getRegionMRT()->getBBSelectRegOut(); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric void LinearizedRegion::setHasLoop(bool Value) { HasLoop = Value; } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric bool LinearizedRegion::getHasLoop() { return HasLoop; } 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric void LinearizedRegion::addLiveOut(unsigned VReg) { LiveOuts.insert(VReg); } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric void LinearizedRegion::removeLiveOut(unsigned Reg) { 8760b57cec5SDimitry Andric if (isLiveOut(Reg)) 8770b57cec5SDimitry Andric LiveOuts.erase(Reg); 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric void LinearizedRegion::replaceLiveOut(unsigned OldReg, unsigned NewReg) { 8810b57cec5SDimitry Andric if (isLiveOut(OldReg)) { 8820b57cec5SDimitry Andric removeLiveOut(OldReg); 8830b57cec5SDimitry Andric addLiveOut(NewReg); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric 887e8d8bef9SDimitry Andric void LinearizedRegion::replaceRegister(unsigned Register, 888e8d8bef9SDimitry Andric class Register NewRegister, 8890b57cec5SDimitry Andric MachineRegisterInfo *MRI, 8900b57cec5SDimitry Andric bool ReplaceInside, bool ReplaceOutside, 8910b57cec5SDimitry Andric bool IncludeLoopPHI) { 8920b57cec5SDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself"); 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric LLVM_DEBUG( 895349cc55cSDimitry Andric dbgs() << "Preparing to replace register (region): " 8960b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) << " with " 8970b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) << "\n"); 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric // If we are replacing outside, we also need to update the LiveOuts 9000b57cec5SDimitry Andric if (ReplaceOutside && 9010b57cec5SDimitry Andric (isLiveOut(Register) || this->getParent()->isLiveOut(Register))) { 9020b57cec5SDimitry Andric LinearizedRegion *Current = this; 9030b57cec5SDimitry Andric while (Current != nullptr && Current->getEntry() != nullptr) { 9040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Region before register replace\n"); 9050b57cec5SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 9060b57cec5SDimitry Andric Current->replaceLiveOut(Register, NewRegister); 9070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Region after register replace\n"); 9080b57cec5SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 9090b57cec5SDimitry Andric Current = Current->getParent(); 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 9140b57cec5SDimitry Andric E = MRI->reg_end(); 9150b57cec5SDimitry Andric I != E;) { 9160b57cec5SDimitry Andric MachineOperand &O = *I; 9170b57cec5SDimitry Andric ++I; 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric // We don't rewrite defs. 9200b57cec5SDimitry Andric if (O.isDef()) 9210b57cec5SDimitry Andric continue; 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric bool IsInside = contains(O.getParent()->getParent()); 9240b57cec5SDimitry Andric bool IsLoopPHI = IsInside && (O.getParent()->isPHI() && 9250b57cec5SDimitry Andric O.getParent()->getParent() == getEntry()); 9260b57cec5SDimitry Andric bool ShouldReplace = (IsInside && ReplaceInside) || 9270b57cec5SDimitry Andric (!IsInside && ReplaceOutside) || 9280b57cec5SDimitry Andric (IncludeLoopPHI && IsLoopPHI); 9290b57cec5SDimitry Andric if (ShouldReplace) { 9300b57cec5SDimitry Andric 931e8d8bef9SDimitry Andric if (NewRegister.isPhysical()) { 9320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: " 9330b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 9340b57cec5SDimitry Andric << "\n"); 9350b57cec5SDimitry Andric llvm_unreachable("Cannot substitute physical registers"); 9360b57cec5SDimitry Andric } else { 9370b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register (region): " 9380b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) 9390b57cec5SDimitry Andric << " with " 9400b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 9410b57cec5SDimitry Andric << "\n"); 9420b57cec5SDimitry Andric O.setReg(NewRegister); 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric void LinearizedRegion::replaceRegisterInsideRegion(unsigned Register, 9490b57cec5SDimitry Andric unsigned NewRegister, 9500b57cec5SDimitry Andric bool IncludeLoopPHIs, 9510b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 9520b57cec5SDimitry Andric replaceRegister(Register, NewRegister, MRI, true, false, IncludeLoopPHIs); 9530b57cec5SDimitry Andric } 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric void LinearizedRegion::replaceRegisterOutsideRegion(unsigned Register, 9560b57cec5SDimitry Andric unsigned NewRegister, 9570b57cec5SDimitry Andric bool IncludeLoopPHIs, 9580b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 9590b57cec5SDimitry Andric replaceRegister(Register, NewRegister, MRI, false, true, IncludeLoopPHIs); 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric DenseSet<unsigned> *LinearizedRegion::getLiveOuts() { return &LiveOuts; } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric void LinearizedRegion::setEntry(MachineBasicBlock *NewEntry) { 9650b57cec5SDimitry Andric Entry = NewEntry; 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric MachineBasicBlock *LinearizedRegion::getEntry() { return Entry; } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric void LinearizedRegion::setExit(MachineBasicBlock *NewExit) { Exit = NewExit; } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric MachineBasicBlock *LinearizedRegion::getExit() { return Exit; } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric void LinearizedRegion::addMBB(MachineBasicBlock *MBB) { MBBs.insert(MBB); } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric void LinearizedRegion::addMBBs(LinearizedRegion *InnerRegion) { 977bdd1243dSDimitry Andric for (auto *MBB : InnerRegion->MBBs) { 9780b57cec5SDimitry Andric addMBB(MBB); 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric bool LinearizedRegion::contains(MachineBasicBlock *MBB) { 983e8d8bef9SDimitry Andric return MBBs.contains(MBB); 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric 9860b57cec5SDimitry Andric bool LinearizedRegion::isLiveOut(unsigned Reg) { 987e8d8bef9SDimitry Andric return LiveOuts.contains(Reg); 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric bool LinearizedRegion::hasNoDef(unsigned Reg, MachineRegisterInfo *MRI) { 9910b57cec5SDimitry Andric return MRI->def_begin(Reg) == MRI->def_end(); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric // After the code has been structurized, what was flagged as kills 9950b57cec5SDimitry Andric // before are no longer register kills. 9960b57cec5SDimitry Andric void LinearizedRegion::removeFalseRegisterKills(MachineRegisterInfo *MRI) { 9970b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); 9988bcb0991SDimitry Andric (void)TRI; // It's used by LLVM_DEBUG. 9998bcb0991SDimitry Andric 1000bdd1243dSDimitry Andric for (auto *MBBI : MBBs) { 10010b57cec5SDimitry Andric MachineBasicBlock *MBB = MBBI; 10020b57cec5SDimitry Andric for (auto &II : *MBB) { 10030b57cec5SDimitry Andric for (auto &RI : II.uses()) { 10040b57cec5SDimitry Andric if (RI.isReg()) { 10058bcb0991SDimitry Andric Register Reg = RI.getReg(); 1006e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 10070b57cec5SDimitry Andric if (hasNoDef(Reg, MRI)) 10080b57cec5SDimitry Andric continue; 10090b57cec5SDimitry Andric if (!MRI->hasOneDef(Reg)) { 10100b57cec5SDimitry Andric LLVM_DEBUG(this->getEntry()->getParent()->dump()); 10110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(Reg, TRI) << "\n"); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) { 10150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 10160b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 10170b57cec5SDimitry Andric << " has NO defs\n"); 10180b57cec5SDimitry Andric } else if (!MRI->hasOneDef(Reg)) { 10190b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 10200b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 10210b57cec5SDimitry Andric << " has multiple defs\n"); 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 10250b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(Reg))); 10260b57cec5SDimitry Andric MachineOperand *UseOperand = &(RI); 10270b57cec5SDimitry Andric bool UseIsOutsideDefMBB = Def->getParent()->getParent() != MBB; 10280b57cec5SDimitry Andric if (UseIsOutsideDefMBB && UseOperand->isKill()) { 10290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Removing kill flag on register: " 10300b57cec5SDimitry Andric << printReg(Reg, TRI) << "\n"); 10310b57cec5SDimitry Andric UseOperand->setIsKill(false); 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric } 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric void LinearizedRegion::initLiveOut(RegionMRT *Region, 10410b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 10420b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 10430b57cec5SDimitry Andric PHILinearize &PHIInfo) { 10440b57cec5SDimitry Andric storeLiveOuts(Region, MRI, TRI, PHIInfo); 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric LinearizedRegion::LinearizedRegion(MachineBasicBlock *MBB, 10480b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 10490b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 10500b57cec5SDimitry Andric PHILinearize &PHIInfo) { 10510b57cec5SDimitry Andric setEntry(MBB); 10520b57cec5SDimitry Andric setExit(MBB); 10530b57cec5SDimitry Andric storeLiveOuts(MBB, MRI, TRI, PHIInfo); 10540b57cec5SDimitry Andric MBBs.insert(MBB); 10550b57cec5SDimitry Andric Parent = nullptr; 10560b57cec5SDimitry Andric } 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric LinearizedRegion::LinearizedRegion() { 10590b57cec5SDimitry Andric setEntry(nullptr); 10600b57cec5SDimitry Andric setExit(nullptr); 10610b57cec5SDimitry Andric Parent = nullptr; 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric namespace { 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric class AMDGPUMachineCFGStructurizer : public MachineFunctionPass { 10670b57cec5SDimitry Andric private: 10680b57cec5SDimitry Andric const MachineRegionInfo *Regions; 10690b57cec5SDimitry Andric const SIInstrInfo *TII; 10700b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 10710b57cec5SDimitry Andric MachineRegisterInfo *MRI; 10720b57cec5SDimitry Andric PHILinearize PHIInfo; 10730b57cec5SDimitry Andric DenseMap<MachineBasicBlock *, MachineBasicBlock *> FallthroughMap; 10740b57cec5SDimitry Andric RegionMRT *RMRT; 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric void getPHIRegionIndices(RegionMRT *Region, MachineInstr &PHI, 10770b57cec5SDimitry Andric SmallVector<unsigned, 2> &RegionIndices); 10780b57cec5SDimitry Andric void getPHIRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 10790b57cec5SDimitry Andric SmallVector<unsigned, 2> &RegionIndices); 10800b57cec5SDimitry Andric void getPHINonRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 10810b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices); 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric void storePHILinearizationInfoDest( 10840b57cec5SDimitry Andric unsigned LDestReg, MachineInstr &PHI, 10850b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices = nullptr); 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric unsigned storePHILinearizationInfo(MachineInstr &PHI, 10880b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices); 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric void extractKilledPHIs(MachineBasicBlock *MBB); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric bool shrinkPHI(MachineInstr &PHI, SmallVector<unsigned, 2> &PHIIndices, 10930b57cec5SDimitry Andric unsigned *ReplaceReg); 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric bool shrinkPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 10960b57cec5SDimitry Andric MachineBasicBlock *SourceMBB, 10970b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, unsigned *ReplaceReg); 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric void replacePHI(MachineInstr &PHI, unsigned CombinedSourceReg, 11000b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 11010b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices); 11020b57cec5SDimitry Andric void replaceEntryPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 11030b57cec5SDimitry Andric MachineBasicBlock *IfMBB, 11040b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices); 11050b57cec5SDimitry Andric void replaceLiveOutRegs(MachineInstr &PHI, 11060b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices, 11070b57cec5SDimitry Andric unsigned CombinedSourceReg, 11080b57cec5SDimitry Andric LinearizedRegion *LRegion); 11090b57cec5SDimitry Andric void rewriteRegionExitPHI(RegionMRT *Region, MachineBasicBlock *LastMerge, 11100b57cec5SDimitry Andric MachineInstr &PHI, LinearizedRegion *LRegion); 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric void rewriteRegionExitPHIs(RegionMRT *Region, MachineBasicBlock *LastMerge, 11130b57cec5SDimitry Andric LinearizedRegion *LRegion); 11140b57cec5SDimitry Andric void rewriteRegionEntryPHI(LinearizedRegion *Region, MachineBasicBlock *IfMBB, 11150b57cec5SDimitry Andric MachineInstr &PHI); 11160b57cec5SDimitry Andric void rewriteRegionEntryPHIs(LinearizedRegion *Region, 11170b57cec5SDimitry Andric MachineBasicBlock *IfMBB); 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric bool regionIsSimpleIf(RegionMRT *Region); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric void transformSimpleIfRegion(RegionMRT *Region); 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric void insertUnconditionalBranch(MachineBasicBlock *MBB, 11240b57cec5SDimitry Andric MachineBasicBlock *Dest, 11250b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc()); 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric MachineBasicBlock *createLinearizedExitBlock(RegionMRT *Region); 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric void insertMergePHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11300b57cec5SDimitry Andric MachineBasicBlock *MergeBB, unsigned DestRegister, 11310b57cec5SDimitry Andric unsigned IfSourceRegister, unsigned CodeSourceRegister, 11320b57cec5SDimitry Andric bool IsUndefIfSource = false); 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric MachineBasicBlock *createIfBlock(MachineBasicBlock *MergeBB, 11350b57cec5SDimitry Andric MachineBasicBlock *CodeBBStart, 11360b57cec5SDimitry Andric MachineBasicBlock *CodeBBEnd, 11370b57cec5SDimitry Andric MachineBasicBlock *SelectBB, unsigned IfReg, 11380b57cec5SDimitry Andric bool InheritPreds); 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric void prunePHIInfo(MachineBasicBlock *MBB); 11410b57cec5SDimitry Andric void createEntryPHI(LinearizedRegion *CurrentRegion, unsigned DestReg); 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric void createEntryPHIs(LinearizedRegion *CurrentRegion); 11440b57cec5SDimitry Andric void resolvePHIInfos(MachineBasicBlock *FunctionEntry); 11450b57cec5SDimitry Andric 1146e8d8bef9SDimitry Andric void replaceRegisterWith(unsigned Register, class Register NewRegister); 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric MachineBasicBlock *createIfRegion(MachineBasicBlock *MergeBB, 11490b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 11500b57cec5SDimitry Andric LinearizedRegion *LRegion, 11510b57cec5SDimitry Andric unsigned BBSelectRegIn, 11520b57cec5SDimitry Andric unsigned BBSelectRegOut); 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric MachineBasicBlock * 11550b57cec5SDimitry Andric createIfRegion(MachineBasicBlock *MergeMBB, LinearizedRegion *InnerRegion, 11560b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 11570b57cec5SDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut); 11580b57cec5SDimitry Andric void ensureCondIsNotKilled(SmallVector<MachineOperand, 1> Cond); 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric void rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 11610b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11620b57cec5SDimitry Andric unsigned BBSelectReg); 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric MachineInstr *getDefInstr(unsigned Reg); 11650b57cec5SDimitry Andric void insertChainedPHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11660b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11670b57cec5SDimitry Andric LinearizedRegion *InnerRegion, unsigned DestReg, 11680b57cec5SDimitry Andric unsigned SourceReg); 11690b57cec5SDimitry Andric bool containsDef(MachineBasicBlock *MBB, LinearizedRegion *InnerRegion, 11700b57cec5SDimitry Andric unsigned Register); 11710b57cec5SDimitry Andric void rewriteLiveOutRegs(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11720b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11730b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 11740b57cec5SDimitry Andric LinearizedRegion *LRegion); 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric void splitLoopPHI(MachineInstr &PHI, MachineBasicBlock *Entry, 11770b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, LinearizedRegion *LRegion); 11780b57cec5SDimitry Andric void splitLoopPHIs(MachineBasicBlock *Entry, MachineBasicBlock *EntrySucc, 11790b57cec5SDimitry Andric LinearizedRegion *LRegion); 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric MachineBasicBlock *splitExit(LinearizedRegion *LRegion); 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric MachineBasicBlock *splitEntry(LinearizedRegion *LRegion); 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric LinearizedRegion *initLinearizedRegion(RegionMRT *Region); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric bool structurizeComplexRegion(RegionMRT *Region); 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric bool structurizeRegion(RegionMRT *Region); 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric bool structurizeRegions(RegionMRT *Region, bool isTopRegion); 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric public: 11940b57cec5SDimitry Andric static char ID; 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer() : MachineFunctionPass(ID) { 11970b57cec5SDimitry Andric initializeAMDGPUMachineCFGStructurizerPass(*PassRegistry::getPassRegistry()); 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 12010b57cec5SDimitry Andric AU.addRequired<MachineRegionInfoPass>(); 12020b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric void initFallthroughMap(MachineFunction &MF); 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric void createLinearizedRegion(RegionMRT *Region, unsigned SelectOut); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric unsigned initializeSelectRegisters(MRT *MRT, unsigned ExistingExitReg, 12100b57cec5SDimitry Andric MachineRegisterInfo *MRI, 12110b57cec5SDimitry Andric const SIInstrInfo *TII); 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric void setRegionMRT(RegionMRT *RegionTree) { RMRT = RegionTree; } 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric RegionMRT *getRegionMRT() { return RMRT; } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 12180b57cec5SDimitry Andric }; 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric } // end anonymous namespace 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric char AMDGPUMachineCFGStructurizer::ID = 0; 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::regionIsSimpleIf(RegionMRT *Region) { 12250b57cec5SDimitry Andric MachineBasicBlock *Entry = Region->getEntry(); 12260b57cec5SDimitry Andric MachineBasicBlock *Succ = Region->getSucc(); 12270b57cec5SDimitry Andric bool FoundBypass = false; 12280b57cec5SDimitry Andric bool FoundIf = false; 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric if (Entry->succ_size() != 2) { 12310b57cec5SDimitry Andric return false; 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric 1234349cc55cSDimitry Andric for (MachineBasicBlock *Current : Entry->successors()) { 12350b57cec5SDimitry Andric if (Current == Succ) { 12360b57cec5SDimitry Andric FoundBypass = true; 12370b57cec5SDimitry Andric } else if ((Current->succ_size() == 1) && 12380b57cec5SDimitry Andric *(Current->succ_begin()) == Succ) { 12390b57cec5SDimitry Andric FoundIf = true; 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric } 12420b57cec5SDimitry Andric 12430b57cec5SDimitry Andric return FoundIf && FoundBypass; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::transformSimpleIfRegion(RegionMRT *Region) { 12470b57cec5SDimitry Andric MachineBasicBlock *Entry = Region->getEntry(); 12480b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getExit(); 12490b57cec5SDimitry Andric TII->convertNonUniformIfRegion(Entry, Exit); 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric static void fixMBBTerminator(MachineBasicBlock *MBB) { 12530b57cec5SDimitry Andric if (MBB->succ_size() == 1) { 12540b57cec5SDimitry Andric auto *Succ = *(MBB->succ_begin()); 12550b57cec5SDimitry Andric for (auto &TI : MBB->terminators()) { 12560b57cec5SDimitry Andric for (auto &UI : TI.uses()) { 12570b57cec5SDimitry Andric if (UI.isMBB() && UI.getMBB() != Succ) { 12580b57cec5SDimitry Andric UI.setMBB(Succ); 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric static void fixRegionTerminator(RegionMRT *Region) { 12660b57cec5SDimitry Andric MachineBasicBlock *InternalSucc = nullptr; 12670b57cec5SDimitry Andric MachineBasicBlock *ExternalSucc = nullptr; 12680b57cec5SDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion(); 12690b57cec5SDimitry Andric auto Exit = LRegion->getExit(); 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 2> Successors; 1272349cc55cSDimitry Andric for (MachineBasicBlock *Succ : Exit->successors()) { 12730b57cec5SDimitry Andric if (LRegion->contains(Succ)) { 12740b57cec5SDimitry Andric // Do not allow re-assign 12750b57cec5SDimitry Andric assert(InternalSucc == nullptr); 12760b57cec5SDimitry Andric InternalSucc = Succ; 12770b57cec5SDimitry Andric } else { 12780b57cec5SDimitry Andric // Do not allow re-assign 12790b57cec5SDimitry Andric assert(ExternalSucc == nullptr); 12800b57cec5SDimitry Andric ExternalSucc = Succ; 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric } 12830b57cec5SDimitry Andric 12840b57cec5SDimitry Andric for (auto &TI : Exit->terminators()) { 12850b57cec5SDimitry Andric for (auto &UI : TI.uses()) { 12860b57cec5SDimitry Andric if (UI.isMBB()) { 12870b57cec5SDimitry Andric auto Target = UI.getMBB(); 12880b57cec5SDimitry Andric if (Target != InternalSucc && Target != ExternalSucc) { 12890b57cec5SDimitry Andric UI.setMBB(ExternalSucc); 12900b57cec5SDimitry Andric } 12910b57cec5SDimitry Andric } 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric 129681ad6265SDimitry Andric // If a region is just a sequence of regions (and the exit 12970b57cec5SDimitry Andric // block in the case of the top level region), we can simply skip 12980b57cec5SDimitry Andric // linearizing it, because it is already linear 12990b57cec5SDimitry Andric bool regionIsSequence(RegionMRT *Region) { 13000b57cec5SDimitry Andric auto Children = Region->getChildren(); 1301bdd1243dSDimitry Andric for (auto *CI : *Children) { 13020b57cec5SDimitry Andric if (!CI->isRegion()) { 13030b57cec5SDimitry Andric if (CI->getMBBMRT()->getMBB()->succ_size() > 1) { 13040b57cec5SDimitry Andric return false; 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric } 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric return true; 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric void fixupRegionExits(RegionMRT *Region) { 13120b57cec5SDimitry Andric auto Children = Region->getChildren(); 1313bdd1243dSDimitry Andric for (auto *CI : *Children) { 13140b57cec5SDimitry Andric if (!CI->isRegion()) { 13150b57cec5SDimitry Andric fixMBBTerminator(CI->getMBBMRT()->getMBB()); 13160b57cec5SDimitry Andric } else { 13170b57cec5SDimitry Andric fixRegionTerminator(CI->getRegionMRT()); 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric } 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 13230b57cec5SDimitry Andric RegionMRT *Region, MachineInstr &PHI, 13240b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 13250b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13260b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13270b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13280b57cec5SDimitry Andric if (Region->contains(Pred)) { 13290b57cec5SDimitry Andric PHIRegionIndices.push_back(i); 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric } 13320b57cec5SDimitry Andric } 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 13350b57cec5SDimitry Andric LinearizedRegion *Region, MachineInstr &PHI, 13360b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 13370b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13380b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13390b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13400b57cec5SDimitry Andric if (Region->contains(Pred)) { 13410b57cec5SDimitry Andric PHIRegionIndices.push_back(i); 13420b57cec5SDimitry Andric } 13430b57cec5SDimitry Andric } 13440b57cec5SDimitry Andric } 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHINonRegionIndices( 13470b57cec5SDimitry Andric LinearizedRegion *Region, MachineInstr &PHI, 13480b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices) { 13490b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13500b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13510b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13520b57cec5SDimitry Andric if (!Region->contains(Pred)) { 13530b57cec5SDimitry Andric PHINonRegionIndices.push_back(i); 13540b57cec5SDimitry Andric } 13550b57cec5SDimitry Andric } 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::storePHILinearizationInfoDest( 13590b57cec5SDimitry Andric unsigned LDestReg, MachineInstr &PHI, 13600b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices) { 13610b57cec5SDimitry Andric if (RegionIndices) { 13620b57cec5SDimitry Andric for (auto i : *RegionIndices) { 13630b57cec5SDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric } else { 13660b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13670b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13680b57cec5SDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric } 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric unsigned AMDGPUMachineCFGStructurizer::storePHILinearizationInfo( 13740b57cec5SDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> *RegionIndices) { 13750b57cec5SDimitry Andric unsigned DestReg = getPHIDestReg(PHI); 13768bcb0991SDimitry Andric Register LinearizeDestReg = 13770b57cec5SDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(DestReg)); 13780b57cec5SDimitry Andric PHIInfo.addDest(LinearizeDestReg, PHI.getDebugLoc()); 13790b57cec5SDimitry Andric storePHILinearizationInfoDest(LinearizeDestReg, PHI, RegionIndices); 13800b57cec5SDimitry Andric return LinearizeDestReg; 13810b57cec5SDimitry Andric } 13820b57cec5SDimitry Andric 13830b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::extractKilledPHIs(MachineBasicBlock *MBB) { 13840b57cec5SDimitry Andric // We need to create a new chain for the killed phi, but there is no 13850b57cec5SDimitry Andric // need to do the renaming outside or inside the block. 13860b57cec5SDimitry Andric SmallPtrSet<MachineInstr *, 2> PHIs; 13870b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), 13880b57cec5SDimitry Andric E = MBB->instr_end(); 13890b57cec5SDimitry Andric I != E; ++I) { 13900b57cec5SDimitry Andric MachineInstr &Instr = *I; 13910b57cec5SDimitry Andric if (Instr.isPHI()) { 13920b57cec5SDimitry Andric unsigned PHIDestReg = getPHIDestReg(Instr); 1393349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Extracting killed phi:\n"); 13940b57cec5SDimitry Andric LLVM_DEBUG(Instr.dump()); 13950b57cec5SDimitry Andric PHIs.insert(&Instr); 13960b57cec5SDimitry Andric PHIInfo.addDest(PHIDestReg, Instr.getDebugLoc()); 13970b57cec5SDimitry Andric storePHILinearizationInfoDest(PHIDestReg, Instr); 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric 1401bdd1243dSDimitry Andric for (auto *PI : PHIs) { 14020b57cec5SDimitry Andric PI->eraseFromParent(); 14030b57cec5SDimitry Andric } 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric static bool isPHIRegionIndex(SmallVector<unsigned, 2> PHIRegionIndices, 14070b57cec5SDimitry Andric unsigned Index) { 1408fe6060f1SDimitry Andric return llvm::is_contained(PHIRegionIndices, Index); 14090b57cec5SDimitry Andric } 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 14120b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, 14130b57cec5SDimitry Andric unsigned *ReplaceReg) { 14140b57cec5SDimitry Andric return shrinkPHI(PHI, 0, nullptr, PHIIndices, ReplaceReg); 14150b57cec5SDimitry Andric } 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 14180b57cec5SDimitry Andric unsigned CombinedSourceReg, 14190b57cec5SDimitry Andric MachineBasicBlock *SourceMBB, 14200b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, 14210b57cec5SDimitry Andric unsigned *ReplaceReg) { 14220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Shrink PHI: "); 14230b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 14240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " to " << printReg(getPHIDestReg(PHI), TRI) 14250b57cec5SDimitry Andric << " = PHI("); 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andric bool Replaced = false; 14280b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 14290b57cec5SDimitry Andric int SingleExternalEntryIndex = -1; 14300b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14310b57cec5SDimitry Andric if (!isPHIRegionIndex(PHIIndices, i)) { 14320b57cec5SDimitry Andric if (SingleExternalEntryIndex == -1) { 14330b57cec5SDimitry Andric // Single entry 14340b57cec5SDimitry Andric SingleExternalEntryIndex = i; 14350b57cec5SDimitry Andric } else { 14360b57cec5SDimitry Andric // Multiple entries 14370b57cec5SDimitry Andric SingleExternalEntryIndex = -2; 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric } 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric if (SingleExternalEntryIndex > -1) { 14430b57cec5SDimitry Andric *ReplaceReg = getPHISourceReg(PHI, SingleExternalEntryIndex); 14440b57cec5SDimitry Andric // We should not rewrite the code, we should only pick up the single value 14450b57cec5SDimitry Andric // that represents the shrunk PHI. 14460b57cec5SDimitry Andric Replaced = true; 14470b57cec5SDimitry Andric } else { 14480b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 14490b57cec5SDimitry Andric MachineInstrBuilder MIB = 14500b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 14510b57cec5SDimitry Andric getPHIDestReg(PHI)); 14520b57cec5SDimitry Andric if (SourceMBB) { 14530b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 14540b57cec5SDimitry Andric MIB.addMBB(SourceMBB); 14550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 14560b57cec5SDimitry Andric << printMBBReference(*SourceMBB)); 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14600b57cec5SDimitry Andric if (isPHIRegionIndex(PHIIndices, i)) { 14610b57cec5SDimitry Andric continue; 14620b57cec5SDimitry Andric } 14630b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 14640b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 14650b57cec5SDimitry Andric MIB.addReg(SourceReg); 14660b57cec5SDimitry Andric MIB.addMBB(SourcePred); 14670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 14680b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 14690b57cec5SDimitry Andric } 14700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric PHI.eraseFromParent(); 14730b57cec5SDimitry Andric return Replaced; 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replacePHI( 14770b57cec5SDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *LastMerge, 14780b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 14790b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replace PHI: "); 14800b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 14810b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " with " << printReg(getPHIDestReg(PHI), TRI) 14820b57cec5SDimitry Andric << " = PHI("); 14830b57cec5SDimitry Andric 14840b57cec5SDimitry Andric bool HasExternalEdge = false; 14850b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 14860b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14870b57cec5SDimitry Andric if (!isPHIRegionIndex(PHIRegionIndices, i)) { 14880b57cec5SDimitry Andric HasExternalEdge = true; 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric if (HasExternalEdge) { 14930b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 14940b57cec5SDimitry Andric MachineInstrBuilder MIB = 14950b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 14960b57cec5SDimitry Andric getPHIDestReg(PHI)); 14970b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 14980b57cec5SDimitry Andric MIB.addMBB(LastMerge); 14990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 15000b57cec5SDimitry Andric << printMBBReference(*LastMerge)); 15010b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15020b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15030b57cec5SDimitry Andric continue; 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 15060b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 15070b57cec5SDimitry Andric MIB.addReg(SourceReg); 15080b57cec5SDimitry Andric MIB.addMBB(SourcePred); 15090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 15100b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 15130b57cec5SDimitry Andric } else { 15140b57cec5SDimitry Andric replaceRegisterWith(getPHIDestReg(PHI), CombinedSourceReg); 15150b57cec5SDimitry Andric } 15160b57cec5SDimitry Andric PHI.eraseFromParent(); 15170b57cec5SDimitry Andric } 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceEntryPHI( 15200b57cec5SDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *IfMBB, 15210b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 15220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replace entry PHI: "); 15230b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 15240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " with "); 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 15270b57cec5SDimitry Andric unsigned NumNonRegionInputs = NumInputs; 15280b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15290b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15300b57cec5SDimitry Andric NumNonRegionInputs--; 15310b57cec5SDimitry Andric } 15320b57cec5SDimitry Andric } 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric if (NumNonRegionInputs == 0) { 15350b57cec5SDimitry Andric auto DestReg = getPHIDestReg(PHI); 15360b57cec5SDimitry Andric replaceRegisterWith(DestReg, CombinedSourceReg); 15370b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " register " << printReg(CombinedSourceReg, TRI) 15380b57cec5SDimitry Andric << "\n"); 15390b57cec5SDimitry Andric PHI.eraseFromParent(); 15400b57cec5SDimitry Andric } else { 15410b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(getPHIDestReg(PHI), TRI) << " = PHI("); 15420b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 15430b57cec5SDimitry Andric MachineInstrBuilder MIB = 15440b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 15450b57cec5SDimitry Andric getPHIDestReg(PHI)); 15460b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 15470b57cec5SDimitry Andric MIB.addMBB(IfMBB); 15480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 15490b57cec5SDimitry Andric << printMBBReference(*IfMBB)); 15500b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 15510b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15520b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15530b57cec5SDimitry Andric continue; 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 15560b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 15570b57cec5SDimitry Andric MIB.addReg(SourceReg); 15580b57cec5SDimitry Andric MIB.addMBB(SourcePred); 15590b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 15600b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 15630b57cec5SDimitry Andric PHI.eraseFromParent(); 15640b57cec5SDimitry Andric } 15650b57cec5SDimitry Andric } 15660b57cec5SDimitry Andric 15670b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceLiveOutRegs( 15680b57cec5SDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> &PHIRegionIndices, 15690b57cec5SDimitry Andric unsigned CombinedSourceReg, LinearizedRegion *LRegion) { 15700b57cec5SDimitry Andric bool WasLiveOut = false; 15710b57cec5SDimitry Andric for (auto PII : PHIRegionIndices) { 15720b57cec5SDimitry Andric unsigned Reg = getPHISourceReg(PHI, PII); 15730b57cec5SDimitry Andric if (LRegion->isLiveOut(Reg)) { 15740b57cec5SDimitry Andric bool IsDead = true; 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric // Check if register is live out of the basic block 15770b57cec5SDimitry Andric MachineBasicBlock *DefMBB = getDefInstr(Reg)->getParent(); 1578349cc55cSDimitry Andric for (const MachineOperand &MO : MRI->use_operands(Reg)) 1579349cc55cSDimitry Andric if (MO.getParent()->getParent() != DefMBB) 15800b57cec5SDimitry Andric IsDead = false; 15810b57cec5SDimitry Andric 15820b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " << printReg(Reg, TRI) << " is " 15830b57cec5SDimitry Andric << (IsDead ? "dead" : "alive") 15840b57cec5SDimitry Andric << " after PHI replace\n"); 15850b57cec5SDimitry Andric if (IsDead) { 15860b57cec5SDimitry Andric LRegion->removeLiveOut(Reg); 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric WasLiveOut = true; 15890b57cec5SDimitry Andric } 15900b57cec5SDimitry Andric } 15910b57cec5SDimitry Andric 15920b57cec5SDimitry Andric if (WasLiveOut) 15930b57cec5SDimitry Andric LRegion->addLiveOut(CombinedSourceReg); 15940b57cec5SDimitry Andric } 15950b57cec5SDimitry Andric 15960b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHI(RegionMRT *Region, 15970b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 15980b57cec5SDimitry Andric MachineInstr &PHI, 15990b57cec5SDimitry Andric LinearizedRegion *LRegion) { 16000b57cec5SDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices; 16010b57cec5SDimitry Andric getPHIRegionIndices(Region, PHI, PHIRegionIndices); 16020b57cec5SDimitry Andric unsigned LinearizedSourceReg = 16030b57cec5SDimitry Andric storePHILinearizationInfo(PHI, &PHIRegionIndices); 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric replacePHI(PHI, LinearizedSourceReg, LastMerge, PHIRegionIndices); 16060b57cec5SDimitry Andric replaceLiveOutRegs(PHI, PHIRegionIndices, LinearizedSourceReg, LRegion); 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric 16090b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHI(LinearizedRegion *Region, 16100b57cec5SDimitry Andric MachineBasicBlock *IfMBB, 16110b57cec5SDimitry Andric MachineInstr &PHI) { 16120b57cec5SDimitry Andric SmallVector<unsigned, 2> PHINonRegionIndices; 16130b57cec5SDimitry Andric getPHINonRegionIndices(Region, PHI, PHINonRegionIndices); 16140b57cec5SDimitry Andric unsigned LinearizedSourceReg = 16150b57cec5SDimitry Andric storePHILinearizationInfo(PHI, &PHINonRegionIndices); 16160b57cec5SDimitry Andric replaceEntryPHI(PHI, LinearizedSourceReg, IfMBB, PHINonRegionIndices); 16170b57cec5SDimitry Andric } 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric static void collectPHIs(MachineBasicBlock *MBB, 16200b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> &PHIs) { 16210b57cec5SDimitry Andric for (auto &BBI : *MBB) { 16220b57cec5SDimitry Andric if (BBI.isPHI()) { 16230b57cec5SDimitry Andric PHIs.push_back(&BBI); 16240b57cec5SDimitry Andric } 16250b57cec5SDimitry Andric } 16260b57cec5SDimitry Andric } 16270b57cec5SDimitry Andric 16280b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHIs(RegionMRT *Region, 16290b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 16300b57cec5SDimitry Andric LinearizedRegion *LRegion) { 16310b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 16320b57cec5SDimitry Andric auto Exit = Region->getSucc(); 16330b57cec5SDimitry Andric if (Exit == nullptr) 16340b57cec5SDimitry Andric return; 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric collectPHIs(Exit, PHIs); 16370b57cec5SDimitry Andric 1638bdd1243dSDimitry Andric for (auto *PHII : PHIs) { 16390b57cec5SDimitry Andric rewriteRegionExitPHI(Region, LastMerge, *PHII, LRegion); 16400b57cec5SDimitry Andric } 16410b57cec5SDimitry Andric } 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHIs(LinearizedRegion *Region, 16440b57cec5SDimitry Andric MachineBasicBlock *IfMBB) { 16450b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 16460b57cec5SDimitry Andric auto Entry = Region->getEntry(); 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric collectPHIs(Entry, PHIs); 16490b57cec5SDimitry Andric 1650bdd1243dSDimitry Andric for (auto *PHII : PHIs) { 16510b57cec5SDimitry Andric rewriteRegionEntryPHI(Region, IfMBB, *PHII); 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertUnconditionalBranch(MachineBasicBlock *MBB, 16560b57cec5SDimitry Andric MachineBasicBlock *Dest, 16570b57cec5SDimitry Andric const DebugLoc &DL) { 16580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting unconditional branch: " << MBB->getNumber() 16590b57cec5SDimitry Andric << " -> " << Dest->getNumber() << "\n"); 16600b57cec5SDimitry Andric MachineBasicBlock::instr_iterator Terminator = MBB->getFirstInstrTerminator(); 16610b57cec5SDimitry Andric bool HasTerminator = Terminator != MBB->instr_end(); 16620b57cec5SDimitry Andric if (HasTerminator) { 16630b57cec5SDimitry Andric TII->ReplaceTailWithBranchTo(Terminator, Dest); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(Dest)) { 16660b57cec5SDimitry Andric TII->insertUnconditionalBranch(*MBB, Dest, DL); 16670b57cec5SDimitry Andric } 16680b57cec5SDimitry Andric } 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric static MachineBasicBlock *getSingleExitNode(MachineFunction &MF) { 16710b57cec5SDimitry Andric MachineBasicBlock *result = nullptr; 16720b57cec5SDimitry Andric for (auto &MFI : MF) { 1673349cc55cSDimitry Andric if (MFI.succ_empty()) { 16740b57cec5SDimitry Andric if (result == nullptr) { 16750b57cec5SDimitry Andric result = &MFI; 16760b57cec5SDimitry Andric } else { 16770b57cec5SDimitry Andric return nullptr; 16780b57cec5SDimitry Andric } 16790b57cec5SDimitry Andric } 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric return result; 16830b57cec5SDimitry Andric } 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric static bool hasOneExitNode(MachineFunction &MF) { 16860b57cec5SDimitry Andric return getSingleExitNode(MF) != nullptr; 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric MachineBasicBlock * 16900b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::createLinearizedExitBlock(RegionMRT *Region) { 16910b57cec5SDimitry Andric auto Exit = Region->getSucc(); 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric // If the exit is the end of the function, we just use the existing 16940b57cec5SDimitry Andric MachineFunction *MF = Region->getEntry()->getParent(); 16950b57cec5SDimitry Andric if (Exit == nullptr && hasOneExitNode(*MF)) { 16960b57cec5SDimitry Andric return &(*(--(Region->getEntry()->getParent()->end()))); 16970b57cec5SDimitry Andric } 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric MachineBasicBlock *LastMerge = MF->CreateMachineBasicBlock(); 17000b57cec5SDimitry Andric if (Exit == nullptr) { 17010b57cec5SDimitry Andric MachineFunction::iterator ExitIter = MF->end(); 17020b57cec5SDimitry Andric MF->insert(ExitIter, LastMerge); 17030b57cec5SDimitry Andric } else { 17040b57cec5SDimitry Andric MachineFunction::iterator ExitIter = Exit->getIterator(); 17050b57cec5SDimitry Andric MF->insert(ExitIter, LastMerge); 17060b57cec5SDimitry Andric LastMerge->addSuccessor(Exit); 17070b57cec5SDimitry Andric insertUnconditionalBranch(LastMerge, Exit); 17080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created exit block: " << LastMerge->getNumber() 17090b57cec5SDimitry Andric << "\n"); 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric return LastMerge; 17120b57cec5SDimitry Andric } 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertMergePHI(MachineBasicBlock *IfBB, 17150b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 17160b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 17170b57cec5SDimitry Andric unsigned DestRegister, 17180b57cec5SDimitry Andric unsigned IfSourceRegister, 17190b57cec5SDimitry Andric unsigned CodeSourceRegister, 17200b57cec5SDimitry Andric bool IsUndefIfSource) { 17210b57cec5SDimitry Andric // If this is the function exit block, we don't need a phi. 17227a6dacacSDimitry Andric if (MergeBB->succ_empty()) { 17230b57cec5SDimitry Andric return; 17240b57cec5SDimitry Andric } 17250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Merge PHI (" << printMBBReference(*MergeBB) 17260b57cec5SDimitry Andric << "): " << printReg(DestRegister, TRI) << " = PHI(" 17270b57cec5SDimitry Andric << printReg(IfSourceRegister, TRI) << ", " 17280b57cec5SDimitry Andric << printMBBReference(*IfBB) 17290b57cec5SDimitry Andric << printReg(CodeSourceRegister, TRI) << ", " 17300b57cec5SDimitry Andric << printMBBReference(*CodeBB) << ")\n"); 17310b57cec5SDimitry Andric const DebugLoc &DL = MergeBB->findDebugLoc(MergeBB->begin()); 17320b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*MergeBB, MergeBB->instr_begin(), DL, 17330b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), DestRegister); 17340b57cec5SDimitry Andric if (IsUndefIfSource && false) { 17350b57cec5SDimitry Andric MIB.addReg(IfSourceRegister, RegState::Undef); 17360b57cec5SDimitry Andric } else { 17370b57cec5SDimitry Andric MIB.addReg(IfSourceRegister); 17380b57cec5SDimitry Andric } 17390b57cec5SDimitry Andric MIB.addMBB(IfBB); 17400b57cec5SDimitry Andric MIB.addReg(CodeSourceRegister); 17410b57cec5SDimitry Andric MIB.addMBB(CodeBB); 17420b57cec5SDimitry Andric } 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric static void removeExternalCFGSuccessors(MachineBasicBlock *MBB) { 17450b57cec5SDimitry Andric for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(), 17460b57cec5SDimitry Andric E = MBB->succ_end(); 17470b57cec5SDimitry Andric PI != E; ++PI) { 17480b57cec5SDimitry Andric if ((*PI) != MBB) { 17490b57cec5SDimitry Andric (MBB)->removeSuccessor(*PI); 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric } 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric static void removeExternalCFGEdges(MachineBasicBlock *StartMBB, 17550b57cec5SDimitry Andric MachineBasicBlock *EndMBB) { 17560b57cec5SDimitry Andric 1757349cc55cSDimitry Andric // We have to check against the StartMBB successor because a 17580b57cec5SDimitry Andric // structurized region with a loop will have the entry block split, 17590b57cec5SDimitry Andric // and the backedge will go to the entry successor. 17600b57cec5SDimitry Andric DenseSet<std::pair<MachineBasicBlock *, MachineBasicBlock *>> Succs; 17610b57cec5SDimitry Andric unsigned SuccSize = StartMBB->succ_size(); 17620b57cec5SDimitry Andric if (SuccSize > 0) { 17630b57cec5SDimitry Andric MachineBasicBlock *StartMBBSucc = *(StartMBB->succ_begin()); 1764349cc55cSDimitry Andric for (MachineBasicBlock *Succ : EndMBB->successors()) { 17650b57cec5SDimitry Andric // Either we have a back-edge to the entry block, or a back-edge to the 17660b57cec5SDimitry Andric // successor of the entry block since the block may be split. 1767349cc55cSDimitry Andric if (Succ != StartMBB && 1768349cc55cSDimitry Andric !(Succ == StartMBBSucc && StartMBB != EndMBB && SuccSize == 1)) { 17690b57cec5SDimitry Andric Succs.insert( 1770349cc55cSDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *>(EndMBB, Succ)); 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric } 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 1775349cc55cSDimitry Andric for (MachineBasicBlock *Pred : StartMBB->predecessors()) 1776349cc55cSDimitry Andric if (Pred != EndMBB) 1777bdd1243dSDimitry Andric Succs.insert(std::pair(Pred, StartMBB)); 17780b57cec5SDimitry Andric 17790b57cec5SDimitry Andric for (auto SI : Succs) { 17800b57cec5SDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *> Edge = SI; 17810b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Removing edge: " << printMBBReference(*Edge.first) 17820b57cec5SDimitry Andric << " -> " << printMBBReference(*Edge.second) << "\n"); 17830b57cec5SDimitry Andric Edge.first->removeSuccessor(Edge.second); 17840b57cec5SDimitry Andric } 17850b57cec5SDimitry Andric } 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfBlock( 17880b57cec5SDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBBStart, 17890b57cec5SDimitry Andric MachineBasicBlock *CodeBBEnd, MachineBasicBlock *SelectBB, unsigned IfReg, 17900b57cec5SDimitry Andric bool InheritPreds) { 17910b57cec5SDimitry Andric MachineFunction *MF = MergeBB->getParent(); 17920b57cec5SDimitry Andric MachineBasicBlock *IfBB = MF->CreateMachineBasicBlock(); 17930b57cec5SDimitry Andric 17940b57cec5SDimitry Andric if (InheritPreds) { 1795349cc55cSDimitry Andric for (MachineBasicBlock *Pred : CodeBBStart->predecessors()) 1796349cc55cSDimitry Andric if (Pred != CodeBBEnd) 17970b57cec5SDimitry Andric Pred->addSuccessor(IfBB); 17980b57cec5SDimitry Andric } 17990b57cec5SDimitry Andric 18000b57cec5SDimitry Andric removeExternalCFGEdges(CodeBBStart, CodeBBEnd); 18010b57cec5SDimitry Andric 18020b57cec5SDimitry Andric auto CodeBBStartI = CodeBBStart->getIterator(); 18030b57cec5SDimitry Andric auto CodeBBEndI = CodeBBEnd->getIterator(); 18040b57cec5SDimitry Andric auto MergeIter = MergeBB->getIterator(); 18050b57cec5SDimitry Andric MF->insert(MergeIter, IfBB); 18060b57cec5SDimitry Andric MF->splice(MergeIter, CodeBBStartI, ++CodeBBEndI); 18070b57cec5SDimitry Andric IfBB->addSuccessor(MergeBB); 18080b57cec5SDimitry Andric IfBB->addSuccessor(CodeBBStart); 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created If block: " << IfBB->getNumber() << "\n"); 18110b57cec5SDimitry Andric // Ensure that the MergeBB is a successor of the CodeEndBB. 18120b57cec5SDimitry Andric if (!CodeBBEnd->isSuccessor(MergeBB)) 18130b57cec5SDimitry Andric CodeBBEnd->addSuccessor(MergeBB); 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Moved " << printMBBReference(*CodeBBStart) 18160b57cec5SDimitry Andric << " through " << printMBBReference(*CodeBBEnd) << "\n"); 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric // If we have a single predecessor we can find a reasonable debug location 18190b57cec5SDimitry Andric MachineBasicBlock *SinglePred = 18200b57cec5SDimitry Andric CodeBBStart->pred_size() == 1 ? *(CodeBBStart->pred_begin()) : nullptr; 18210b57cec5SDimitry Andric const DebugLoc &DL = SinglePred 18220b57cec5SDimitry Andric ? SinglePred->findDebugLoc(SinglePred->getFirstTerminator()) 18230b57cec5SDimitry Andric : DebugLoc(); 18240b57cec5SDimitry Andric 1825e8d8bef9SDimitry Andric Register Reg = 18260b57cec5SDimitry Andric TII->insertEQ(IfBB, IfBB->begin(), DL, IfReg, 18270b57cec5SDimitry Andric SelectBB->getNumber() /* CodeBBStart->getNumber() */); 18280b57cec5SDimitry Andric if (&(*(IfBB->getParent()->begin())) == IfBB) { 18290b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->begin(), DL, IfReg, 18300b57cec5SDimitry Andric CodeBBStart->getNumber()); 18310b57cec5SDimitry Andric } 18320b57cec5SDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 18330b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 18340b57cec5SDimitry Andric TII->insertBranch(*IfBB, MergeBB, CodeBBStart, Cond, DL); 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric return IfBB; 18370b57cec5SDimitry Andric } 18380b57cec5SDimitry Andric 18390b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::ensureCondIsNotKilled( 18400b57cec5SDimitry Andric SmallVector<MachineOperand, 1> Cond) { 18410b57cec5SDimitry Andric if (Cond.size() != 1) 18420b57cec5SDimitry Andric return; 18430b57cec5SDimitry Andric if (!Cond[0].isReg()) 18440b57cec5SDimitry Andric return; 18450b57cec5SDimitry Andric 18468bcb0991SDimitry Andric Register CondReg = Cond[0].getReg(); 1847349cc55cSDimitry Andric for (MachineOperand &MO : MRI->use_operands(CondReg)) 1848349cc55cSDimitry Andric MO.setIsKill(false); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric 18510b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 18520b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 18530b57cec5SDimitry Andric unsigned BBSelectReg) { 18540b57cec5SDimitry Andric MachineBasicBlock *TrueBB = nullptr; 18550b57cec5SDimitry Andric MachineBasicBlock *FalseBB = nullptr; 18560b57cec5SDimitry Andric SmallVector<MachineOperand, 1> Cond; 18570b57cec5SDimitry Andric MachineBasicBlock *FallthroughBB = FallthroughMap[CodeBB]; 18580b57cec5SDimitry Andric TII->analyzeBranch(*CodeBB, TrueBB, FalseBB, Cond); 18590b57cec5SDimitry Andric 18600b57cec5SDimitry Andric const DebugLoc &DL = CodeBB->findDebugLoc(CodeBB->getFirstTerminator()); 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr && FallthroughBB == nullptr) { 18630b57cec5SDimitry Andric // This is an exit block, hence no successors. We will assign the 18640b57cec5SDimitry Andric // bb select register to the entry block. 18650b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18660b57cec5SDimitry Andric BBSelectReg, 18670b57cec5SDimitry Andric CodeBB->getParent()->begin()->getNumber()); 18680b57cec5SDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL); 18690b57cec5SDimitry Andric return; 18700b57cec5SDimitry Andric } 18710b57cec5SDimitry Andric 18720b57cec5SDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr) { 18730b57cec5SDimitry Andric TrueBB = FallthroughBB; 18740b57cec5SDimitry Andric } else if (TrueBB != nullptr) { 18750b57cec5SDimitry Andric FalseBB = 18760b57cec5SDimitry Andric (FallthroughBB && (FallthroughBB != TrueBB)) ? FallthroughBB : FalseBB; 18770b57cec5SDimitry Andric } 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric if ((TrueBB != nullptr && FalseBB == nullptr) || (TrueBB == FalseBB)) { 18800b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18810b57cec5SDimitry Andric BBSelectReg, TrueBB->getNumber()); 18820b57cec5SDimitry Andric } else { 18830b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectReg); 18848bcb0991SDimitry Andric Register TrueBBReg = MRI->createVirtualRegister(RegClass); 18858bcb0991SDimitry Andric Register FalseBBReg = MRI->createVirtualRegister(RegClass); 18860b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18870b57cec5SDimitry Andric TrueBBReg, TrueBB->getNumber()); 18880b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18890b57cec5SDimitry Andric FalseBBReg, FalseBB->getNumber()); 18900b57cec5SDimitry Andric ensureCondIsNotKilled(Cond); 18910b57cec5SDimitry Andric TII->insertVectorSelect(*CodeBB, CodeBB->getFirstTerminator(), DL, 18920b57cec5SDimitry Andric BBSelectReg, Cond, TrueBBReg, FalseBBReg); 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL); 18960b57cec5SDimitry Andric } 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric MachineInstr *AMDGPUMachineCFGStructurizer::getDefInstr(unsigned Reg) { 18990b57cec5SDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) { 19000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 19010b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 19020b57cec5SDimitry Andric << " has NO defs\n"); 19030b57cec5SDimitry Andric } else if (!MRI->hasOneDef(Reg)) { 19040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 19050b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 19060b57cec5SDimitry Andric << " has multiple defs\n"); 19070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS BEGIN:\n"); 19080b57cec5SDimitry Andric for (auto DI = MRI->def_begin(Reg), DE = MRI->def_end(); DI != DE; ++DI) { 19090b57cec5SDimitry Andric LLVM_DEBUG(DI->getParent()->dump()); 19100b57cec5SDimitry Andric } 19110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS END\n"); 19120b57cec5SDimitry Andric } 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 19150b57cec5SDimitry Andric return (*(MRI->def_begin(Reg))).getParent(); 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric 19180b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertChainedPHI(MachineBasicBlock *IfBB, 19190b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 19200b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 19210b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19220b57cec5SDimitry Andric unsigned DestReg, 19230b57cec5SDimitry Andric unsigned SourceReg) { 19240b57cec5SDimitry Andric // In this function we know we are part of a chain already, so we need 19250b57cec5SDimitry Andric // to add the registers to the existing chain, and rename the register 19260b57cec5SDimitry Andric // inside the region. 19270b57cec5SDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 19280b57cec5SDimitry Andric MachineInstr *DefInstr = getDefInstr(SourceReg); 19290b57cec5SDimitry Andric if (DefInstr->isPHI() && DefInstr->getParent() == CodeBB && IsSingleBB) { 19300b57cec5SDimitry Andric // Handle the case where the def is a PHI-def inside a basic 19310b57cec5SDimitry Andric // block, then we only need to do renaming. Special care needs to 19320b57cec5SDimitry Andric // be taken if the PHI-def is part of an existing chain, or if a 19330b57cec5SDimitry Andric // new one needs to be created. 19340b57cec5SDimitry Andric InnerRegion->replaceRegisterInsideRegion(SourceReg, DestReg, true, MRI); 19350b57cec5SDimitry Andric 19360b57cec5SDimitry Andric // We collect all PHI Information, and if we are at the region entry, 19370b57cec5SDimitry Andric // all PHIs will be removed, and then re-introduced if needed. 19380b57cec5SDimitry Andric storePHILinearizationInfoDest(DestReg, *DefInstr); 19390b57cec5SDimitry Andric // We have picked up all the information we need now and can remove 19400b57cec5SDimitry Andric // the PHI 19410b57cec5SDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 19420b57cec5SDimitry Andric DefInstr->eraseFromParent(); 19430b57cec5SDimitry Andric } else { 19440b57cec5SDimitry Andric // If this is not a phi-def, or it is a phi-def but from a linearized region 19450b57cec5SDimitry Andric if (IsSingleBB && DefInstr->getParent() == InnerRegion->getEntry()) { 19460b57cec5SDimitry Andric // If this is a single BB and the definition is in this block we 19470b57cec5SDimitry Andric // need to replace any uses outside the region. 19480b57cec5SDimitry Andric InnerRegion->replaceRegisterOutsideRegion(SourceReg, DestReg, false, MRI); 19490b57cec5SDimitry Andric } 19500b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(DestReg); 19518bcb0991SDimitry Andric Register NextDestReg = MRI->createVirtualRegister(RegClass); 19520b57cec5SDimitry Andric bool IsLastDef = PHIInfo.getNumSources(DestReg) == 1; 19530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Chained PHI\n"); 19540b57cec5SDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, DestReg, NextDestReg, 19550b57cec5SDimitry Andric SourceReg, IsLastDef); 19560b57cec5SDimitry Andric 19570b57cec5SDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 19580b57cec5SDimitry Andric if (IsLastDef) { 19590b57cec5SDimitry Andric const DebugLoc &DL = IfBB->findDebugLoc(IfBB->getFirstTerminator()); 19600b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DL, 19610b57cec5SDimitry Andric NextDestReg, 0); 19620b57cec5SDimitry Andric PHIInfo.deleteDef(DestReg); 19630b57cec5SDimitry Andric } else { 19640b57cec5SDimitry Andric PHIInfo.replaceDef(DestReg, NextDestReg); 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric } 19670b57cec5SDimitry Andric } 19680b57cec5SDimitry Andric 19690b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::containsDef(MachineBasicBlock *MBB, 19700b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19710b57cec5SDimitry Andric unsigned Register) { 19720b57cec5SDimitry Andric return getDefInstr(Register)->getParent() == MBB || 19730b57cec5SDimitry Andric InnerRegion->contains(getDefInstr(Register)->getParent()); 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteLiveOutRegs(MachineBasicBlock *IfBB, 19770b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 19780b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 19790b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19800b57cec5SDimitry Andric LinearizedRegion *LRegion) { 19810b57cec5SDimitry Andric DenseSet<unsigned> *LiveOuts = InnerRegion->getLiveOuts(); 19820b57cec5SDimitry Andric SmallVector<unsigned, 4> OldLiveOuts; 19830b57cec5SDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 19840b57cec5SDimitry Andric for (auto OLI : *LiveOuts) { 19850b57cec5SDimitry Andric OldLiveOuts.push_back(OLI); 19860b57cec5SDimitry Andric } 19870b57cec5SDimitry Andric 19880b57cec5SDimitry Andric for (auto LI : OldLiveOuts) { 19890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LiveOut: " << printReg(LI, TRI)); 19900b57cec5SDimitry Andric if (!containsDef(CodeBB, InnerRegion, LI) || 19910b57cec5SDimitry Andric (!IsSingleBB && (getDefInstr(LI)->getParent() == LRegion->getExit()))) { 1992349cc55cSDimitry Andric // If the register simply lives through the CodeBB, we don't have 19930b57cec5SDimitry Andric // to rewrite anything since the register is not defined in this 19940b57cec5SDimitry Andric // part of the code. 19950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "- through"); 19960b57cec5SDimitry Andric continue; 19970b57cec5SDimitry Andric } 19980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 19990b57cec5SDimitry Andric unsigned Reg = LI; 20000b57cec5SDimitry Andric if (/*!PHIInfo.isSource(Reg) &&*/ Reg != InnerRegion->getBBSelectRegOut()) { 20010b57cec5SDimitry Andric // If the register is live out, we do want to create a phi, 2002349cc55cSDimitry Andric // unless it is from the Exit block, because in that case there 20030b57cec5SDimitry Andric // is already a PHI, and no need to create a new one. 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric // If the register is just a live out def and not part of a phi 20060b57cec5SDimitry Andric // chain, we need to create a PHI node to handle the if region, 20070b57cec5SDimitry Andric // and replace all uses outside of the region with the new dest 20080b57cec5SDimitry Andric // register, unless it is the outgoing BB select register. We have 2009349cc55cSDimitry Andric // already created phi nodes for these. 20100b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(Reg); 20118bcb0991SDimitry Andric Register PHIDestReg = MRI->createVirtualRegister(RegClass); 20128bcb0991SDimitry Andric Register IfSourceReg = MRI->createVirtualRegister(RegClass); 20130b57cec5SDimitry Andric // Create initializer, this value is never used, but is needed 20140b57cec5SDimitry Andric // to satisfy SSA. 20150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Initializer for reg: " << printReg(Reg) << "\n"); 20160b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DebugLoc(), 20170b57cec5SDimitry Andric IfSourceReg, 0); 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric InnerRegion->replaceRegisterOutsideRegion(Reg, PHIDestReg, true, MRI); 20200b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Non-Chained Live out PHI\n"); 20210b57cec5SDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, PHIDestReg, 20220b57cec5SDimitry Andric IfSourceReg, Reg, true); 20230b57cec5SDimitry Andric } 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric 20260b57cec5SDimitry Andric // Handle the chained definitions in PHIInfo, checking if this basic block 20270b57cec5SDimitry Andric // is a source block for a definition. 20280b57cec5SDimitry Andric SmallVector<unsigned, 4> Sources; 20290b57cec5SDimitry Andric if (PHIInfo.findSourcesFromMBB(CodeBB, Sources)) { 20300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting PHI Live Out from " 20310b57cec5SDimitry Andric << printMBBReference(*CodeBB) << "\n"); 20320b57cec5SDimitry Andric for (auto SI : Sources) { 20330b57cec5SDimitry Andric unsigned DestReg; 20340b57cec5SDimitry Andric PHIInfo.findDest(SI, CodeBB, DestReg); 20350b57cec5SDimitry Andric insertChainedPHI(IfBB, CodeBB, MergeBB, InnerRegion, DestReg, SI); 20360b57cec5SDimitry Andric } 20370b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insertion done.\n"); 20380b57cec5SDimitry Andric } 20390b57cec5SDimitry Andric 20400b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::prunePHIInfo(MachineBasicBlock *MBB) { 20440b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Before PHI Prune\n"); 20450b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20460b57cec5SDimitry Andric SmallVector<std::tuple<unsigned, unsigned, MachineBasicBlock *>, 4> 20470b57cec5SDimitry Andric ElimiatedSources; 20480b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 20490b57cec5SDimitry Andric ++DRI) { 20500b57cec5SDimitry Andric 20510b57cec5SDimitry Andric unsigned DestReg = *DRI; 20520b57cec5SDimitry Andric auto SE = PHIInfo.sources_end(DestReg); 20530b57cec5SDimitry Andric 20540b57cec5SDimitry Andric bool MBBContainsPHISource = false; 20550b57cec5SDimitry Andric // Check if there is a PHI source in this MBB 20560b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 20570b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 20580b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 20590b57cec5SDimitry Andric if (Def->getParent()->getParent() == MBB) { 20600b57cec5SDimitry Andric MBBContainsPHISource = true; 20610b57cec5SDimitry Andric } 20620b57cec5SDimitry Andric } 20630b57cec5SDimitry Andric 20640b57cec5SDimitry Andric // If so, all other sources are useless since we know this block 20650b57cec5SDimitry Andric // is always executed when the region is executed. 20660b57cec5SDimitry Andric if (MBBContainsPHISource) { 20670b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 20680b57cec5SDimitry Andric PHILinearize::PHISourceT Source = *SRI; 20690b57cec5SDimitry Andric unsigned SourceReg = Source.first; 20700b57cec5SDimitry Andric MachineBasicBlock *SourceMBB = Source.second; 20710b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 20720b57cec5SDimitry Andric if (Def->getParent()->getParent() != MBB) { 2073bdd1243dSDimitry Andric ElimiatedSources.push_back(std::tuple(DestReg, SourceReg, SourceMBB)); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric } 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric } 20780b57cec5SDimitry Andric 20790b57cec5SDimitry Andric // Remove the PHI sources that are in the given MBB 20800b57cec5SDimitry Andric for (auto &SourceInfo : ElimiatedSources) { 20810b57cec5SDimitry Andric PHIInfo.removeSource(std::get<0>(SourceInfo), std::get<1>(SourceInfo), 20820b57cec5SDimitry Andric std::get<2>(SourceInfo)); 20830b57cec5SDimitry Andric } 20840b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "After PHI Prune\n"); 20850b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric 20880b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegion, 20890b57cec5SDimitry Andric unsigned DestReg) { 20900b57cec5SDimitry Andric MachineBasicBlock *Entry = CurrentRegion->getEntry(); 20910b57cec5SDimitry Andric MachineBasicBlock *Exit = CurrentRegion->getExit(); 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExit: " << Exit->getNumber() << " Pred: " 20940b57cec5SDimitry Andric << (*(Entry->pred_begin()))->getNumber() << "\n"); 20950b57cec5SDimitry Andric 20960b57cec5SDimitry Andric int NumSources = 0; 20970b57cec5SDimitry Andric auto SE = PHIInfo.sources_end(DestReg); 20980b57cec5SDimitry Andric 20990b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 21000b57cec5SDimitry Andric NumSources++; 21010b57cec5SDimitry Andric } 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric if (NumSources == 1) { 21040b57cec5SDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg); 21050b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 21060b57cec5SDimitry Andric replaceRegisterWith(DestReg, SourceReg); 21070b57cec5SDimitry Andric } else { 21080b57cec5SDimitry Andric const DebugLoc &DL = Entry->findDebugLoc(Entry->begin()); 21090b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*Entry, Entry->instr_begin(), DL, 21100b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), DestReg); 21110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Entry PHI " << printReg(DestReg, TRI) << " = PHI("); 21120b57cec5SDimitry Andric 21130b57cec5SDimitry Andric unsigned CurrentBackedgeReg = 0; 21140b57cec5SDimitry Andric 21150b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 21160b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric if (CurrentRegion->contains((*SRI).second)) { 21190b57cec5SDimitry Andric if (CurrentBackedgeReg == 0) { 21200b57cec5SDimitry Andric CurrentBackedgeReg = SourceReg; 21210b57cec5SDimitry Andric } else { 21220b57cec5SDimitry Andric MachineInstr *PHIDefInstr = getDefInstr(SourceReg); 21230b57cec5SDimitry Andric MachineBasicBlock *PHIDefMBB = PHIDefInstr->getParent(); 21240b57cec5SDimitry Andric const TargetRegisterClass *RegClass = 21250b57cec5SDimitry Andric MRI->getRegClass(CurrentBackedgeReg); 21268bcb0991SDimitry Andric Register NewBackedgeReg = MRI->createVirtualRegister(RegClass); 21270b57cec5SDimitry Andric MachineInstrBuilder BackedgePHI = 21280b57cec5SDimitry Andric BuildMI(*PHIDefMBB, PHIDefMBB->instr_begin(), DL, 21290b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), NewBackedgeReg); 21300b57cec5SDimitry Andric BackedgePHI.addReg(CurrentBackedgeReg); 21310b57cec5SDimitry Andric BackedgePHI.addMBB(getPHIPred(*PHIDefInstr, 0)); 21320b57cec5SDimitry Andric BackedgePHI.addReg(getPHISourceReg(*PHIDefInstr, 1)); 21330b57cec5SDimitry Andric BackedgePHI.addMBB((*SRI).second); 21340b57cec5SDimitry Andric CurrentBackedgeReg = NewBackedgeReg; 21350b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 21360b57cec5SDimitry Andric << "Inserting backedge PHI: " 21370b57cec5SDimitry Andric << printReg(NewBackedgeReg, TRI) << " = PHI(" 21380b57cec5SDimitry Andric << printReg(CurrentBackedgeReg, TRI) << ", " 21390b57cec5SDimitry Andric << printMBBReference(*getPHIPred(*PHIDefInstr, 0)) << ", " 21400b57cec5SDimitry Andric << printReg(getPHISourceReg(*PHIDefInstr, 1), TRI) << ", " 21410b57cec5SDimitry Andric << printMBBReference(*(*SRI).second)); 21420b57cec5SDimitry Andric } 21430b57cec5SDimitry Andric } else { 21440b57cec5SDimitry Andric MIB.addReg(SourceReg); 21450b57cec5SDimitry Andric MIB.addMBB((*SRI).second); 21460b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 21470b57cec5SDimitry Andric << printMBBReference(*(*SRI).second) << ", "); 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric // Add the final backedge register source to the entry phi 21520b57cec5SDimitry Andric if (CurrentBackedgeReg != 0) { 21530b57cec5SDimitry Andric MIB.addReg(CurrentBackedgeReg); 21540b57cec5SDimitry Andric MIB.addMBB(Exit); 21550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CurrentBackedgeReg, TRI) << ", " 21560b57cec5SDimitry Andric << printMBBReference(*Exit) << ")\n"); 21570b57cec5SDimitry Andric } else { 21580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 21590b57cec5SDimitry Andric } 21600b57cec5SDimitry Andric } 21610b57cec5SDimitry Andric } 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHIs(LinearizedRegion *CurrentRegion) { 21640b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 21650b57cec5SDimitry Andric 21660b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 21670b57cec5SDimitry Andric ++DRI) { 21680b57cec5SDimitry Andric 21690b57cec5SDimitry Andric unsigned DestReg = *DRI; 21700b57cec5SDimitry Andric createEntryPHI(CurrentRegion, DestReg); 21710b57cec5SDimitry Andric } 21720b57cec5SDimitry Andric PHIInfo.clear(); 21730b57cec5SDimitry Andric } 21740b57cec5SDimitry Andric 2175e8d8bef9SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceRegisterWith( 2176e8d8bef9SDimitry Andric unsigned Register, class Register NewRegister) { 21770b57cec5SDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself"); 21780b57cec5SDimitry Andric 21790b57cec5SDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 21800b57cec5SDimitry Andric E = MRI->reg_end(); 21810b57cec5SDimitry Andric I != E;) { 21820b57cec5SDimitry Andric MachineOperand &O = *I; 21830b57cec5SDimitry Andric ++I; 2184e8d8bef9SDimitry Andric if (NewRegister.isPhysical()) { 21850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: " 21860b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 21870b57cec5SDimitry Andric << "\n"); 21880b57cec5SDimitry Andric llvm_unreachable("Cannot substitute physical registers"); 21890b57cec5SDimitry Andric // We don't handle physical registers, but if we need to 21900b57cec5SDimitry Andric // in the future This is how we do it: 21910b57cec5SDimitry Andric // O.substPhysReg(NewRegister, *TRI); 21920b57cec5SDimitry Andric } else { 21930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register: " 21940b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) 21950b57cec5SDimitry Andric << " with " 21960b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 21970b57cec5SDimitry Andric << "\n"); 21980b57cec5SDimitry Andric O.setReg(NewRegister); 21990b57cec5SDimitry Andric } 22000b57cec5SDimitry Andric } 22010b57cec5SDimitry Andric PHIInfo.deleteDef(Register); 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 22040b57cec5SDimitry Andric 22050b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 22060b57cec5SDimitry Andric } 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::resolvePHIInfos(MachineBasicBlock *FunctionEntry) { 22090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Resolve PHI Infos\n"); 22100b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 22110b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 22120b57cec5SDimitry Andric ++DRI) { 22130b57cec5SDimitry Andric unsigned DestReg = *DRI; 22140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI) << "\n"); 22150b57cec5SDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg); 22160b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 22170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI) 22180b57cec5SDimitry Andric << " SourceReg: " << printReg(SourceReg, TRI) << "\n"); 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric assert(PHIInfo.sources_end(DestReg) == ++SRI && 22210b57cec5SDimitry Andric "More than one phi source in entry node"); 22220b57cec5SDimitry Andric replaceRegisterWith(DestReg, SourceReg); 22230b57cec5SDimitry Andric } 22240b57cec5SDimitry Andric } 22250b57cec5SDimitry Andric 22260b57cec5SDimitry Andric static bool isFunctionEntryBlock(MachineBasicBlock *MBB) { 22270b57cec5SDimitry Andric return ((&(*(MBB->getParent()->begin()))) == MBB); 22280b57cec5SDimitry Andric } 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 22310b57cec5SDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBB, 22320b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, unsigned BBSelectRegIn, 22330b57cec5SDimitry Andric unsigned BBSelectRegOut) { 22340b57cec5SDimitry Andric if (isFunctionEntryBlock(CodeBB) && !CurrentRegion->getHasLoop()) { 22350b57cec5SDimitry Andric // Handle non-loop function entry block. 22360b57cec5SDimitry Andric // We need to allow loops to the entry block and then 22370b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 22380b57cec5SDimitry Andric resolvePHIInfos(CodeBB); 22390b57cec5SDimitry Andric removeExternalCFGSuccessors(CodeBB); 22400b57cec5SDimitry Andric CodeBB->addSuccessor(MergeBB); 22410b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 22420b57cec5SDimitry Andric return nullptr; 22430b57cec5SDimitry Andric } 22440b57cec5SDimitry Andric if (CurrentRegion->getEntry() == CodeBB && !CurrentRegion->getHasLoop()) { 22450b57cec5SDimitry Andric // Handle non-loop region entry block. 22460b57cec5SDimitry Andric MachineFunction *MF = MergeBB->getParent(); 22470b57cec5SDimitry Andric auto MergeIter = MergeBB->getIterator(); 22480b57cec5SDimitry Andric auto CodeBBStartIter = CodeBB->getIterator(); 22490b57cec5SDimitry Andric auto CodeBBEndIter = ++(CodeBB->getIterator()); 22500b57cec5SDimitry Andric if (CodeBBEndIter != MergeIter) { 22510b57cec5SDimitry Andric MF->splice(MergeIter, CodeBBStartIter, CodeBBEndIter); 22520b57cec5SDimitry Andric } 22530b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 22540b57cec5SDimitry Andric prunePHIInfo(CodeBB); 22550b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 22560b57cec5SDimitry Andric removeExternalCFGSuccessors(CodeBB); 22570b57cec5SDimitry Andric CodeBB->addSuccessor(MergeBB); 22580b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 22590b57cec5SDimitry Andric return nullptr; 2260*0fca6ea1SDimitry Andric } 22610b57cec5SDimitry Andric // Handle internal block. 22620b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectRegIn); 22638bcb0991SDimitry Andric Register CodeBBSelectReg = MRI->createVirtualRegister(RegClass); 22640b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, CodeBBSelectReg); 22650b57cec5SDimitry Andric bool IsRegionEntryBB = CurrentRegion->getEntry() == CodeBB; 22660b57cec5SDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeBB, CodeBB, CodeBB, 22670b57cec5SDimitry Andric BBSelectRegIn, IsRegionEntryBB); 22680b57cec5SDimitry Andric CurrentRegion->addMBB(IfBB); 22690b57cec5SDimitry Andric // If this is the entry block we need to make the If block the new 22700b57cec5SDimitry Andric // linearized region entry. 22710b57cec5SDimitry Andric if (IsRegionEntryBB) { 22720b57cec5SDimitry Andric CurrentRegion->setEntry(IfBB); 22730b57cec5SDimitry Andric 22740b57cec5SDimitry Andric if (CurrentRegion->getHasLoop()) { 22750b57cec5SDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 22760b57cec5SDimitry Andric MachineBasicBlock *ETrueBB = nullptr; 22770b57cec5SDimitry Andric MachineBasicBlock *EFalseBB = nullptr; 22780b57cec5SDimitry Andric SmallVector<MachineOperand, 1> ECond; 22790b57cec5SDimitry Andric 22800b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc(); 22810b57cec5SDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 22820b57cec5SDimitry Andric TII->removeBranch(*RegionExit); 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric // We need to create a backedge if there is a loop 2285*0fca6ea1SDimitry Andric Register Reg = 2286*0fca6ea1SDimitry Andric TII->insertNE(RegionExit, RegionExit->instr_end(), DL, 22870b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 22880b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 2289*0fca6ea1SDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 22900b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 22910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: "); 2292*0fca6ea1SDimitry Andric LLVM_DEBUG(RegOp.print(dbgs(), TRI)); 22930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 22940b57cec5SDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 22950b57cec5SDimitry Andric Cond, DebugLoc()); 22960b57cec5SDimitry Andric RegionExit->addSuccessor(CurrentRegion->getEntry()); 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric } 22990b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 23000b57cec5SDimitry Andric LinearizedRegion InnerRegion(CodeBB, MRI, TRI, PHIInfo); 23010b57cec5SDimitry Andric 23020b57cec5SDimitry Andric InnerRegion.setParent(CurrentRegion); 23030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (BB)\n"); 23040b57cec5SDimitry Andric insertMergePHI(IfBB, CodeBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 23050b57cec5SDimitry Andric CodeBBSelectReg); 23060b57cec5SDimitry Andric InnerRegion.addMBB(MergeBB); 23070b57cec5SDimitry Andric 23080b57cec5SDimitry Andric LLVM_DEBUG(InnerRegion.print(dbgs(), TRI)); 23090b57cec5SDimitry Andric rewriteLiveOutRegs(IfBB, CodeBB, MergeBB, &InnerRegion, CurrentRegion); 23100b57cec5SDimitry Andric extractKilledPHIs(CodeBB); 2311*0fca6ea1SDimitry Andric if (IsRegionEntryBB) 23120b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 23130b57cec5SDimitry Andric return IfBB; 23140b57cec5SDimitry Andric } 23150b57cec5SDimitry Andric 23160b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 23170b57cec5SDimitry Andric MachineBasicBlock *MergeBB, LinearizedRegion *InnerRegion, 23180b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 23190b57cec5SDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut) { 23200b57cec5SDimitry Andric unsigned CodeBBSelectReg = 23210b57cec5SDimitry Andric InnerRegion->getRegionMRT()->getInnerOutputRegister(); 23220b57cec5SDimitry Andric MachineBasicBlock *CodeEntryBB = InnerRegion->getEntry(); 23230b57cec5SDimitry Andric MachineBasicBlock *CodeExitBB = InnerRegion->getExit(); 23240b57cec5SDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeEntryBB, CodeExitBB, 23250b57cec5SDimitry Andric SelectBB, BBSelectRegIn, true); 23260b57cec5SDimitry Andric CurrentRegion->addMBB(IfBB); 23270b57cec5SDimitry Andric bool isEntry = CurrentRegion->getEntry() == InnerRegion->getEntry(); 23280b57cec5SDimitry Andric if (isEntry) { 23290b57cec5SDimitry Andric 23300b57cec5SDimitry Andric if (CurrentRegion->getHasLoop()) { 23310b57cec5SDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 23320b57cec5SDimitry Andric MachineBasicBlock *ETrueBB = nullptr; 23330b57cec5SDimitry Andric MachineBasicBlock *EFalseBB = nullptr; 23340b57cec5SDimitry Andric SmallVector<MachineOperand, 1> ECond; 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc(); 23370b57cec5SDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 23380b57cec5SDimitry Andric TII->removeBranch(*RegionExit); 23390b57cec5SDimitry Andric 23400b57cec5SDimitry Andric // We need to create a backedge if there is a loop 2341e8d8bef9SDimitry Andric Register Reg = 23420b57cec5SDimitry Andric TII->insertNE(RegionExit, RegionExit->instr_end(), DL, 23430b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 23440b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 23450b57cec5SDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 23460b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 23470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: "); 23480b57cec5SDimitry Andric LLVM_DEBUG(Cond[0].print(dbgs(), TRI)); 23490b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 23500b57cec5SDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 23510b57cec5SDimitry Andric Cond, DebugLoc()); 23520b57cec5SDimitry Andric RegionExit->addSuccessor(IfBB); 23530b57cec5SDimitry Andric } 23540b57cec5SDimitry Andric } 23550b57cec5SDimitry Andric CurrentRegion->addMBBs(InnerRegion); 23560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (region)\n"); 23570b57cec5SDimitry Andric insertMergePHI(IfBB, CodeExitBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 23580b57cec5SDimitry Andric CodeBBSelectReg); 23590b57cec5SDimitry Andric 23600b57cec5SDimitry Andric rewriteLiveOutRegs(IfBB, /* CodeEntryBB */ CodeExitBB, MergeBB, InnerRegion, 23610b57cec5SDimitry Andric CurrentRegion); 23620b57cec5SDimitry Andric 23630b57cec5SDimitry Andric rewriteRegionEntryPHIs(InnerRegion, IfBB); 23640b57cec5SDimitry Andric 23650b57cec5SDimitry Andric if (isEntry) { 23660b57cec5SDimitry Andric CurrentRegion->setEntry(IfBB); 23670b57cec5SDimitry Andric } 23680b57cec5SDimitry Andric 23690b57cec5SDimitry Andric if (isEntry) { 23700b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric 23730b57cec5SDimitry Andric return IfBB; 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric 23760b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHI(MachineInstr &PHI, 23770b57cec5SDimitry Andric MachineBasicBlock *Entry, 23780b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, 23790b57cec5SDimitry Andric LinearizedRegion *LRegion) { 23800b57cec5SDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices; 23810b57cec5SDimitry Andric getPHIRegionIndices(LRegion, PHI, PHIRegionIndices); 23820b57cec5SDimitry Andric 23830b57cec5SDimitry Andric assert(PHIRegionIndices.size() == 1); 23840b57cec5SDimitry Andric 23850b57cec5SDimitry Andric unsigned RegionIndex = PHIRegionIndices[0]; 23860b57cec5SDimitry Andric unsigned RegionSourceReg = getPHISourceReg(PHI, RegionIndex); 23870b57cec5SDimitry Andric MachineBasicBlock *RegionSourceMBB = getPHIPred(PHI, RegionIndex); 23880b57cec5SDimitry Andric unsigned PHIDest = getPHIDestReg(PHI); 23890b57cec5SDimitry Andric unsigned PHISource = PHIDest; 23900b57cec5SDimitry Andric unsigned ReplaceReg; 23910b57cec5SDimitry Andric 23920b57cec5SDimitry Andric if (shrinkPHI(PHI, PHIRegionIndices, &ReplaceReg)) { 23930b57cec5SDimitry Andric PHISource = ReplaceReg; 23940b57cec5SDimitry Andric } 23950b57cec5SDimitry Andric 23960b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(PHIDest); 23978bcb0991SDimitry Andric Register NewDestReg = MRI->createVirtualRegister(RegClass); 23980b57cec5SDimitry Andric LRegion->replaceRegisterInsideRegion(PHIDest, NewDestReg, false, MRI); 23990b57cec5SDimitry Andric MachineInstrBuilder MIB = 24000b57cec5SDimitry Andric BuildMI(*EntrySucc, EntrySucc->instr_begin(), PHI.getDebugLoc(), 24010b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), NewDestReg); 24020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split Entry PHI " << printReg(NewDestReg, TRI) 24030b57cec5SDimitry Andric << " = PHI("); 24040b57cec5SDimitry Andric MIB.addReg(PHISource); 24050b57cec5SDimitry Andric MIB.addMBB(Entry); 24060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(PHISource, TRI) << ", " 24070b57cec5SDimitry Andric << printMBBReference(*Entry)); 24080b57cec5SDimitry Andric MIB.addReg(RegionSourceReg); 24090b57cec5SDimitry Andric MIB.addMBB(RegionSourceMBB); 24100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " ," << printReg(RegionSourceReg, TRI) << ", " 24110b57cec5SDimitry Andric << printMBBReference(*RegionSourceMBB) << ")\n"); 24120b57cec5SDimitry Andric } 24130b57cec5SDimitry Andric 24140b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHIs(MachineBasicBlock *Entry, 24150b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, 24160b57cec5SDimitry Andric LinearizedRegion *LRegion) { 24170b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 24180b57cec5SDimitry Andric collectPHIs(Entry, PHIs); 24190b57cec5SDimitry Andric 2420bdd1243dSDimitry Andric for (auto *PHII : PHIs) { 24210b57cec5SDimitry Andric splitLoopPHI(*PHII, Entry, EntrySucc, LRegion); 24220b57cec5SDimitry Andric } 24230b57cec5SDimitry Andric } 24240b57cec5SDimitry Andric 24250b57cec5SDimitry Andric // Split the exit block so that we can insert a end control flow 24260b57cec5SDimitry Andric MachineBasicBlock * 24270b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::splitExit(LinearizedRegion *LRegion) { 24280b57cec5SDimitry Andric auto MRTRegion = LRegion->getRegionMRT(); 24290b57cec5SDimitry Andric auto Exit = LRegion->getExit(); 24300b57cec5SDimitry Andric auto MF = Exit->getParent(); 24310b57cec5SDimitry Andric auto Succ = MRTRegion->getSucc(); 24320b57cec5SDimitry Andric 24330b57cec5SDimitry Andric auto NewExit = MF->CreateMachineBasicBlock(); 24340b57cec5SDimitry Andric auto AfterExitIter = Exit->getIterator(); 24350b57cec5SDimitry Andric AfterExitIter++; 24360b57cec5SDimitry Andric MF->insert(AfterExitIter, NewExit); 24370b57cec5SDimitry Andric Exit->removeSuccessor(Succ); 24380b57cec5SDimitry Andric Exit->addSuccessor(NewExit); 24390b57cec5SDimitry Andric NewExit->addSuccessor(Succ); 24400b57cec5SDimitry Andric insertUnconditionalBranch(NewExit, Succ); 24410b57cec5SDimitry Andric LRegion->addMBB(NewExit); 24420b57cec5SDimitry Andric LRegion->setExit(NewExit); 24430b57cec5SDimitry Andric 24440b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created new exit block: " << NewExit->getNumber() 24450b57cec5SDimitry Andric << "\n"); 24460b57cec5SDimitry Andric 24470b57cec5SDimitry Andric // Replace any PHI Predecessors in the successor with NewExit 24480b57cec5SDimitry Andric for (auto &II : *Succ) { 24490b57cec5SDimitry Andric MachineInstr &Instr = II; 24500b57cec5SDimitry Andric 24510b57cec5SDimitry Andric // If we are past the PHI instructions we are done 24520b57cec5SDimitry Andric if (!Instr.isPHI()) 24530b57cec5SDimitry Andric break; 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric int numPreds = getPHINumInputs(Instr); 24560b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 24570b57cec5SDimitry Andric auto Pred = getPHIPred(Instr, i); 24580b57cec5SDimitry Andric if (Pred == Exit) { 24590b57cec5SDimitry Andric setPhiPred(Instr, i, NewExit); 24600b57cec5SDimitry Andric } 24610b57cec5SDimitry Andric } 24620b57cec5SDimitry Andric } 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric return NewExit; 24650b57cec5SDimitry Andric } 24660b57cec5SDimitry Andric 24670b57cec5SDimitry Andric static MachineBasicBlock *split(MachineBasicBlock::iterator I) { 24680b57cec5SDimitry Andric // Create the fall-through block. 24690b57cec5SDimitry Andric MachineBasicBlock *MBB = (*I).getParent(); 24700b57cec5SDimitry Andric MachineFunction *MF = MBB->getParent(); 24710b57cec5SDimitry Andric MachineBasicBlock *SuccMBB = MF->CreateMachineBasicBlock(); 24720b57cec5SDimitry Andric auto MBBIter = ++(MBB->getIterator()); 24730b57cec5SDimitry Andric MF->insert(MBBIter, SuccMBB); 24740b57cec5SDimitry Andric SuccMBB->transferSuccessorsAndUpdatePHIs(MBB); 24750b57cec5SDimitry Andric MBB->addSuccessor(SuccMBB); 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric // Splice the code over. 24780b57cec5SDimitry Andric SuccMBB->splice(SuccMBB->end(), MBB, I, MBB->end()); 24790b57cec5SDimitry Andric 24800b57cec5SDimitry Andric return SuccMBB; 24810b57cec5SDimitry Andric } 24820b57cec5SDimitry Andric 24830b57cec5SDimitry Andric // Split the entry block separating PHI-nodes and the rest of the code 24840b57cec5SDimitry Andric // This is needed to insert an initializer for the bb select register 24850b57cec5SDimitry Andric // inloop regions. 24860b57cec5SDimitry Andric 24870b57cec5SDimitry Andric MachineBasicBlock * 24880b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::splitEntry(LinearizedRegion *LRegion) { 24890b57cec5SDimitry Andric MachineBasicBlock *Entry = LRegion->getEntry(); 24900b57cec5SDimitry Andric MachineBasicBlock *EntrySucc = split(Entry->getFirstNonPHI()); 24910b57cec5SDimitry Andric MachineBasicBlock *Exit = LRegion->getExit(); 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split " << printMBBReference(*Entry) << " to " 24940b57cec5SDimitry Andric << printMBBReference(*Entry) << " -> " 24950b57cec5SDimitry Andric << printMBBReference(*EntrySucc) << "\n"); 24960b57cec5SDimitry Andric LRegion->addMBB(EntrySucc); 24970b57cec5SDimitry Andric 24980b57cec5SDimitry Andric // Make the backedge go to Entry Succ 24990b57cec5SDimitry Andric if (Exit->isSuccessor(Entry)) { 25000b57cec5SDimitry Andric Exit->removeSuccessor(Entry); 25010b57cec5SDimitry Andric } 25020b57cec5SDimitry Andric Exit->addSuccessor(EntrySucc); 25030b57cec5SDimitry Andric MachineInstr &Branch = *(Exit->instr_rbegin()); 25040b57cec5SDimitry Andric for (auto &UI : Branch.uses()) { 25050b57cec5SDimitry Andric if (UI.isMBB() && UI.getMBB() == Entry) { 25060b57cec5SDimitry Andric UI.setMBB(EntrySucc); 25070b57cec5SDimitry Andric } 25080b57cec5SDimitry Andric } 25090b57cec5SDimitry Andric 25100b57cec5SDimitry Andric splitLoopPHIs(Entry, EntrySucc, LRegion); 25110b57cec5SDimitry Andric 25120b57cec5SDimitry Andric return EntrySucc; 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric LinearizedRegion * 25160b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::initLinearizedRegion(RegionMRT *Region) { 25170b57cec5SDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion(); 25180b57cec5SDimitry Andric LRegion->initLiveOut(Region, MRI, TRI, PHIInfo); 25190b57cec5SDimitry Andric LRegion->setEntry(Region->getEntry()); 25200b57cec5SDimitry Andric return LRegion; 25210b57cec5SDimitry Andric } 25220b57cec5SDimitry Andric 25230b57cec5SDimitry Andric static void removeOldExitPreds(RegionMRT *Region) { 25240b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getSucc(); 25250b57cec5SDimitry Andric if (Exit == nullptr) { 25260b57cec5SDimitry Andric return; 25270b57cec5SDimitry Andric } 25280b57cec5SDimitry Andric for (MachineBasicBlock::pred_iterator PI = Exit->pred_begin(), 25290b57cec5SDimitry Andric E = Exit->pred_end(); 25300b57cec5SDimitry Andric PI != E; ++PI) { 25310b57cec5SDimitry Andric if (Region->contains(*PI)) { 25320b57cec5SDimitry Andric (*PI)->removeSuccessor(Exit); 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric } 25360b57cec5SDimitry Andric 25370b57cec5SDimitry Andric static bool mbbHasBackEdge(MachineBasicBlock *MBB, 25380b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 2539349cc55cSDimitry Andric for (MachineBasicBlock *Succ : MBB->successors()) 2540349cc55cSDimitry Andric if (MBBs.contains(Succ)) 25410b57cec5SDimitry Andric return true; 25420b57cec5SDimitry Andric return false; 25430b57cec5SDimitry Andric } 25440b57cec5SDimitry Andric 25450b57cec5SDimitry Andric static bool containsNewBackedge(MRT *Tree, 25460b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 25470b57cec5SDimitry Andric // Need to traverse this in reverse since it is in post order. 25480b57cec5SDimitry Andric if (Tree == nullptr) 25490b57cec5SDimitry Andric return false; 25500b57cec5SDimitry Andric 25510b57cec5SDimitry Andric if (Tree->isMBB()) { 25520b57cec5SDimitry Andric MachineBasicBlock *MBB = Tree->getMBBMRT()->getMBB(); 25530b57cec5SDimitry Andric MBBs.insert(MBB); 25540b57cec5SDimitry Andric if (mbbHasBackEdge(MBB, MBBs)) { 25550b57cec5SDimitry Andric return true; 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric } else { 25580b57cec5SDimitry Andric RegionMRT *Region = Tree->getRegionMRT(); 2559349cc55cSDimitry Andric for (MRT *C : llvm::reverse(*Region->getChildren())) 2560349cc55cSDimitry Andric if (containsNewBackedge(C, MBBs)) 25610b57cec5SDimitry Andric return true; 25620b57cec5SDimitry Andric } 25630b57cec5SDimitry Andric return false; 25640b57cec5SDimitry Andric } 25650b57cec5SDimitry Andric 25660b57cec5SDimitry Andric static bool containsNewBackedge(RegionMRT *Region) { 25670b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> MBBs; 25680b57cec5SDimitry Andric return containsNewBackedge(Region, MBBs); 25690b57cec5SDimitry Andric } 25700b57cec5SDimitry Andric 25710b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeComplexRegion(RegionMRT *Region) { 25720b57cec5SDimitry Andric auto *LRegion = initLinearizedRegion(Region); 25730b57cec5SDimitry Andric LRegion->setHasLoop(containsNewBackedge(Region)); 25740b57cec5SDimitry Andric MachineBasicBlock *LastMerge = createLinearizedExitBlock(Region); 25750b57cec5SDimitry Andric MachineBasicBlock *CurrentMerge = LastMerge; 25760b57cec5SDimitry Andric LRegion->addMBB(LastMerge); 25770b57cec5SDimitry Andric LRegion->setExit(LastMerge); 25780b57cec5SDimitry Andric 25790b57cec5SDimitry Andric rewriteRegionExitPHIs(Region, LastMerge, LRegion); 25800b57cec5SDimitry Andric removeOldExitPreds(Region); 25810b57cec5SDimitry Andric 25820b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 25830b57cec5SDimitry Andric 25840b57cec5SDimitry Andric SetVector<MRT *> *Children = Region->getChildren(); 25850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region Start===============\n"); 25860b57cec5SDimitry Andric if (LRegion->getHasLoop()) { 25870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: Yes\n"); 25880b57cec5SDimitry Andric } else { 25890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: No\n"); 25900b57cec5SDimitry Andric } 25910b57cec5SDimitry Andric 25920b57cec5SDimitry Andric unsigned BBSelectRegIn; 25930b57cec5SDimitry Andric unsigned BBSelectRegOut; 2594*0fca6ea1SDimitry Andric for (MRT *Child : *Children) { 25950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CurrentRegion: \n"); 25960b57cec5SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI)); 25970b57cec5SDimitry Andric 25980b57cec5SDimitry Andric if (Child->isRegion()) { 25990b57cec5SDimitry Andric 26000b57cec5SDimitry Andric LinearizedRegion *InnerLRegion = 26010b57cec5SDimitry Andric Child->getRegionMRT()->getLinearizedRegion(); 26020b57cec5SDimitry Andric // We found the block is the exit of an inner region, we need 26030b57cec5SDimitry Andric // to put it in the current linearized region. 26040b57cec5SDimitry Andric 26050b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing region: "); 26060b57cec5SDimitry Andric LLVM_DEBUG(InnerLRegion->print(dbgs(), TRI)); 26070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 26080b57cec5SDimitry Andric 26090b57cec5SDimitry Andric MachineBasicBlock *InnerEntry = InnerLRegion->getEntry(); 26100b57cec5SDimitry Andric if ((&(*(InnerEntry->getParent()->begin()))) == InnerEntry) { 26110b57cec5SDimitry Andric // Entry has already been linearized, no need to do this region. 26120b57cec5SDimitry Andric unsigned OuterSelect = InnerLRegion->getBBSelectRegOut(); 26130b57cec5SDimitry Andric unsigned InnerSelectReg = 26140b57cec5SDimitry Andric InnerLRegion->getRegionMRT()->getInnerOutputRegister(); 26150b57cec5SDimitry Andric replaceRegisterWith(InnerSelectReg, OuterSelect), 26160b57cec5SDimitry Andric resolvePHIInfos(InnerEntry); 26170b57cec5SDimitry Andric if (!InnerLRegion->getExit()->isSuccessor(CurrentMerge)) 26180b57cec5SDimitry Andric InnerLRegion->getExit()->addSuccessor(CurrentMerge); 26190b57cec5SDimitry Andric continue; 26200b57cec5SDimitry Andric } 26210b57cec5SDimitry Andric 26220b57cec5SDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut(); 26230b57cec5SDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn(); 26240b57cec5SDimitry Andric 26250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI) 26260b57cec5SDimitry Andric << "\n"); 26270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI) 26280b57cec5SDimitry Andric << "\n"); 26290b57cec5SDimitry Andric 26300b57cec5SDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge; 26310b57cec5SDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, InnerLRegion, LRegion, 26320b57cec5SDimitry Andric Child->getRegionMRT()->getEntry(), 26330b57cec5SDimitry Andric BBSelectRegIn, BBSelectRegOut); 26340b57cec5SDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 26350b57cec5SDimitry Andric } else { 26360b57cec5SDimitry Andric MachineBasicBlock *MBB = Child->getMBBMRT()->getMBB(); 26370b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing block: " << MBB->getNumber() << "\n"); 26380b57cec5SDimitry Andric 26390b57cec5SDimitry Andric if (MBB == getSingleExitNode(*(MBB->getParent()))) { 26400b57cec5SDimitry Andric // If this is the exit block then we need to skip to the next. 26410b57cec5SDimitry Andric // The "in" register will be transferred to "out" in the next 26420b57cec5SDimitry Andric // iteration. 26430b57cec5SDimitry Andric continue; 26440b57cec5SDimitry Andric } 26450b57cec5SDimitry Andric 26460b57cec5SDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut(); 26470b57cec5SDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn(); 26480b57cec5SDimitry Andric 26490b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI) 26500b57cec5SDimitry Andric << "\n"); 26510b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI) 26520b57cec5SDimitry Andric << "\n"); 26530b57cec5SDimitry Andric 26540b57cec5SDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge; 26550b57cec5SDimitry Andric // This is a basic block that is not part of an inner region, we 26560b57cec5SDimitry Andric // need to put it in the current linearized region. 26570b57cec5SDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, MBB, LRegion, BBSelectRegIn, 26580b57cec5SDimitry Andric BBSelectRegOut); 26590b57cec5SDimitry Andric if (CurrentMerge) { 26600b57cec5SDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 26610b57cec5SDimitry Andric } 26620b57cec5SDimitry Andric 26630b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 26640b57cec5SDimitry Andric } 26650b57cec5SDimitry Andric } 26660b57cec5SDimitry Andric 26670b57cec5SDimitry Andric LRegion->removeFalseRegisterKills(MRI); 26680b57cec5SDimitry Andric 26690b57cec5SDimitry Andric if (LRegion->getHasLoop()) { 26700b57cec5SDimitry Andric MachineBasicBlock *NewSucc = splitEntry(LRegion); 26710b57cec5SDimitry Andric if (isFunctionEntryBlock(LRegion->getEntry())) { 26720b57cec5SDimitry Andric resolvePHIInfos(LRegion->getEntry()); 26730b57cec5SDimitry Andric } 26740b57cec5SDimitry Andric const DebugLoc &DL = NewSucc->findDebugLoc(NewSucc->getFirstNonPHI()); 26750b57cec5SDimitry Andric unsigned InReg = LRegion->getBBSelectRegIn(); 26768bcb0991SDimitry Andric Register InnerSelectReg = 26770b57cec5SDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(InReg)); 26788bcb0991SDimitry Andric Register NewInReg = MRI->createVirtualRegister(MRI->getRegClass(InReg)); 26790b57cec5SDimitry Andric TII->materializeImmediate(*(LRegion->getEntry()), 26800b57cec5SDimitry Andric LRegion->getEntry()->getFirstTerminator(), DL, 26810b57cec5SDimitry Andric NewInReg, Region->getEntry()->getNumber()); 26820b57cec5SDimitry Andric // Need to be careful about updating the registers inside the region. 26830b57cec5SDimitry Andric LRegion->replaceRegisterInsideRegion(InReg, InnerSelectReg, false, MRI); 26840b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Loop BBSelect Merge PHI:\n"); 26850b57cec5SDimitry Andric insertMergePHI(LRegion->getEntry(), LRegion->getExit(), NewSucc, 26860b57cec5SDimitry Andric InnerSelectReg, NewInReg, 26870b57cec5SDimitry Andric LRegion->getRegionMRT()->getInnerOutputRegister()); 26880b57cec5SDimitry Andric splitExit(LRegion); 26890b57cec5SDimitry Andric TII->convertNonUniformLoopRegion(NewSucc, LastMerge); 26900b57cec5SDimitry Andric } 26910b57cec5SDimitry Andric 26920b57cec5SDimitry Andric if (Region->isRoot()) { 26930b57cec5SDimitry Andric TII->insertReturn(*LastMerge); 26940b57cec5SDimitry Andric } 26950b57cec5SDimitry Andric 26960b57cec5SDimitry Andric LLVM_DEBUG(Region->getEntry()->getParent()->dump()); 26970b57cec5SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI)); 26980b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 26990b57cec5SDimitry Andric 27000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region End===============\n"); 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric Region->setLinearizedRegion(LRegion); 27030b57cec5SDimitry Andric return true; 27040b57cec5SDimitry Andric } 27050b57cec5SDimitry Andric 27060b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegion(RegionMRT *Region) { 27070b57cec5SDimitry Andric if (false && regionIsSimpleIf(Region)) { 27080b57cec5SDimitry Andric transformSimpleIfRegion(Region); 27090b57cec5SDimitry Andric return true; 27100b57cec5SDimitry Andric } 2711*0fca6ea1SDimitry Andric if (regionIsSequence(Region)) 2712*0fca6ea1SDimitry Andric fixupRegionExits(Region); 2713*0fca6ea1SDimitry Andric else 2714*0fca6ea1SDimitry Andric structurizeComplexRegion(Region); 27150b57cec5SDimitry Andric return false; 27160b57cec5SDimitry Andric } 27170b57cec5SDimitry Andric 27180b57cec5SDimitry Andric static int structurize_once = 0; 27190b57cec5SDimitry Andric 27200b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegions(RegionMRT *Region, 27210b57cec5SDimitry Andric bool isTopRegion) { 27220b57cec5SDimitry Andric bool Changed = false; 27230b57cec5SDimitry Andric 27240b57cec5SDimitry Andric auto Children = Region->getChildren(); 2725bdd1243dSDimitry Andric for (auto *CI : *Children) { 27260b57cec5SDimitry Andric if (CI->isRegion()) { 27270b57cec5SDimitry Andric Changed |= structurizeRegions(CI->getRegionMRT(), false); 27280b57cec5SDimitry Andric } 27290b57cec5SDimitry Andric } 27300b57cec5SDimitry Andric 27310b57cec5SDimitry Andric if (structurize_once < 2 || true) { 27320b57cec5SDimitry Andric Changed |= structurizeRegion(Region); 27330b57cec5SDimitry Andric structurize_once++; 27340b57cec5SDimitry Andric } 27350b57cec5SDimitry Andric return Changed; 27360b57cec5SDimitry Andric } 27370b57cec5SDimitry Andric 27380b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::initFallthroughMap(MachineFunction &MF) { 27390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough Map:\n"); 27400b57cec5SDimitry Andric for (auto &MBBI : MF) { 27410b57cec5SDimitry Andric MachineBasicBlock *MBB = MBBI.getFallThrough(); 27420b57cec5SDimitry Andric if (MBB != nullptr) { 27430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough: " << MBBI.getNumber() << " -> " 27440b57cec5SDimitry Andric << MBB->getNumber() << "\n"); 27450b57cec5SDimitry Andric } 27460b57cec5SDimitry Andric FallthroughMap[&MBBI] = MBB; 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric } 27490b57cec5SDimitry Andric 27500b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createLinearizedRegion(RegionMRT *Region, 27510b57cec5SDimitry Andric unsigned SelectOut) { 27520b57cec5SDimitry Andric LinearizedRegion *LRegion = new LinearizedRegion(); 27530b57cec5SDimitry Andric if (SelectOut) { 27540b57cec5SDimitry Andric LRegion->addLiveOut(SelectOut); 27550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (BBSelect): " << printReg(SelectOut, TRI) 27560b57cec5SDimitry Andric << "\n"); 27570b57cec5SDimitry Andric } 27580b57cec5SDimitry Andric LRegion->setRegionMRT(Region); 27590b57cec5SDimitry Andric Region->setLinearizedRegion(LRegion); 27600b57cec5SDimitry Andric LRegion->setParent(Region->getParent() 27610b57cec5SDimitry Andric ? Region->getParent()->getLinearizedRegion() 27620b57cec5SDimitry Andric : nullptr); 27630b57cec5SDimitry Andric } 27640b57cec5SDimitry Andric 27650b57cec5SDimitry Andric unsigned 27660b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::initializeSelectRegisters(MRT *MRT, unsigned SelectOut, 27670b57cec5SDimitry Andric MachineRegisterInfo *MRI, 27680b57cec5SDimitry Andric const SIInstrInfo *TII) { 27690b57cec5SDimitry Andric if (MRT->isRegion()) { 27700b57cec5SDimitry Andric RegionMRT *Region = MRT->getRegionMRT(); 27710b57cec5SDimitry Andric Region->setBBSelectRegOut(SelectOut); 27720b57cec5SDimitry Andric unsigned InnerSelectOut = createBBSelectReg(TII, MRI); 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric // Fixme: Move linearization creation to the original spot 27750b57cec5SDimitry Andric createLinearizedRegion(Region, SelectOut); 27760b57cec5SDimitry Andric 27770eae32dcSDimitry Andric for (auto *CI : *Region->getChildren()) 27780eae32dcSDimitry Andric InnerSelectOut = initializeSelectRegisters(CI, InnerSelectOut, MRI, TII); 27790b57cec5SDimitry Andric MRT->setBBSelectRegIn(InnerSelectOut); 27800b57cec5SDimitry Andric return InnerSelectOut; 2781*0fca6ea1SDimitry Andric } 27820b57cec5SDimitry Andric MRT->setBBSelectRegOut(SelectOut); 27830b57cec5SDimitry Andric unsigned NewSelectIn = createBBSelectReg(TII, MRI); 27840b57cec5SDimitry Andric MRT->setBBSelectRegIn(NewSelectIn); 27850b57cec5SDimitry Andric return NewSelectIn; 27860b57cec5SDimitry Andric } 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric static void checkRegOnlyPHIInputs(MachineFunction &MF) { 27890b57cec5SDimitry Andric for (auto &MBBI : MF) { 2790*0fca6ea1SDimitry Andric for (MachineInstr &Instr : MBBI.instrs()) { 27910b57cec5SDimitry Andric if (Instr.isPHI()) { 27920b57cec5SDimitry Andric int numPreds = getPHINumInputs(Instr); 27930b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 27940b57cec5SDimitry Andric assert(Instr.getOperand(i * 2 + 1).isReg() && 27950b57cec5SDimitry Andric "PHI Operand not a register"); 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric } 27980b57cec5SDimitry Andric } 27990b57cec5SDimitry Andric } 28000b57cec5SDimitry Andric } 28010b57cec5SDimitry Andric 28020b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::runOnMachineFunction(MachineFunction &MF) { 28030b57cec5SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 28040b57cec5SDimitry Andric const SIInstrInfo *TII = ST.getInstrInfo(); 28050b57cec5SDimitry Andric TRI = ST.getRegisterInfo(); 28060b57cec5SDimitry Andric MRI = &(MF.getRegInfo()); 28070b57cec5SDimitry Andric initFallthroughMap(MF); 28080b57cec5SDimitry Andric 28090b57cec5SDimitry Andric checkRegOnlyPHIInputs(MF); 28100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER START----\n"); 28110b57cec5SDimitry Andric LLVM_DEBUG(MF.dump()); 28120b57cec5SDimitry Andric 28130b57cec5SDimitry Andric Regions = &(getAnalysis<MachineRegionInfoPass>().getRegionInfo()); 28140b57cec5SDimitry Andric LLVM_DEBUG(Regions->dump()); 28150b57cec5SDimitry Andric 28160b57cec5SDimitry Andric RegionMRT *RTree = MRT::buildMRT(MF, Regions, TII, MRI); 28170b57cec5SDimitry Andric setRegionMRT(RTree); 28180b57cec5SDimitry Andric initializeSelectRegisters(RTree, 0, MRI, TII); 28190b57cec5SDimitry Andric LLVM_DEBUG(RTree->dump(TRI)); 28200b57cec5SDimitry Andric bool result = structurizeRegions(RTree, true); 28210b57cec5SDimitry Andric delete RTree; 28220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER END----\n"); 28230b57cec5SDimitry Andric initFallthroughMap(MF); 28240b57cec5SDimitry Andric return result; 28250b57cec5SDimitry Andric } 28260b57cec5SDimitry Andric 28270b57cec5SDimitry Andric char AMDGPUMachineCFGStructurizerID = AMDGPUMachineCFGStructurizer::ID; 28280b57cec5SDimitry Andric 28290b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 28300b57cec5SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false) 28310b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineRegionInfoPass) 28320b57cec5SDimitry Andric INITIALIZE_PASS_END(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 28330b57cec5SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false) 28340b57cec5SDimitry Andric 28350b57cec5SDimitry Andric FunctionPass *llvm::createAMDGPUMachineCFGStructurizerPass() { 28360b57cec5SDimitry Andric return new AMDGPUMachineCFGStructurizer(); 28370b57cec5SDimitry Andric } 2838