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) { 1600b57cec5SDimitry 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) { 1710b57cec5SDimitry 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; 1850b57cec5SDimitry 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) { 197*349cc55cSDimitry 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"; 2500b57cec5SDimitry 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 5090b57cec5SDimitry 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"; 5430b57cec5SDimitry 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) { 5690b57cec5SDimitry Andric for (auto CI : Children) { 5700b57cec5SDimitry Andric if (CI->isMBB()) { 5710b57cec5SDimitry Andric if (MBB == CI->getMBBMRT()->getMBB()) { 5720b57cec5SDimitry Andric return true; 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric } else { 5750b57cec5SDimitry Andric if (CI->getRegionMRT()->contains(MBB)) { 5760b57cec5SDimitry Andric return true; 5770b57cec5SDimitry Andric } else if (CI->getRegionMRT()->getLinearizedRegion() != nullptr && 5780b57cec5SDimitry Andric CI->getRegionMRT()->getLinearizedRegion()->contains(MBB)) { 5790b57cec5SDimitry Andric return true; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric return false; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric void replaceLiveOutReg(unsigned Register, unsigned NewRegister) { 5870b57cec5SDimitry Andric LinearizedRegion *LRegion = getLinearizedRegion(); 5880b57cec5SDimitry Andric LRegion->replaceLiveOut(Register, NewRegister); 5890b57cec5SDimitry Andric for (auto &CI : Children) { 5900b57cec5SDimitry Andric if (CI->isRegion()) { 5910b57cec5SDimitry Andric CI->getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric }; 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric } // end anonymous namespace 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric static unsigned createBBSelectReg(const SIInstrInfo *TII, 6000b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 6010b57cec5SDimitry Andric return MRI->createVirtualRegister(TII->getPreferredSelectRegClass(32)); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric MachineBasicBlock * 6050b57cec5SDimitry Andric MRT::initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo, 6060b57cec5SDimitry Andric DenseMap<MachineRegion *, RegionMRT *> &RegionMap) { 6070b57cec5SDimitry Andric for (auto &MFI : MF) { 6080b57cec5SDimitry Andric MachineBasicBlock *ExitMBB = &MFI; 609*349cc55cSDimitry Andric if (ExitMBB->succ_empty()) { 6100b57cec5SDimitry Andric return ExitMBB; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric llvm_unreachable("CFG has no exit block"); 6140b57cec5SDimitry Andric return nullptr; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric RegionMRT *MRT::buildMRT(MachineFunction &MF, 6180b57cec5SDimitry Andric const MachineRegionInfo *RegionInfo, 6190b57cec5SDimitry Andric const SIInstrInfo *TII, MachineRegisterInfo *MRI) { 6200b57cec5SDimitry Andric SmallPtrSet<MachineRegion *, 4> PlacedRegions; 6210b57cec5SDimitry Andric DenseMap<MachineRegion *, RegionMRT *> RegionMap; 6220b57cec5SDimitry Andric MachineRegion *TopLevelRegion = RegionInfo->getTopLevelRegion(); 6230b57cec5SDimitry Andric RegionMRT *Result = new RegionMRT(TopLevelRegion); 6240b57cec5SDimitry Andric RegionMap[TopLevelRegion] = Result; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric // Insert the exit block first, we need it to be the merge node 6270b57cec5SDimitry Andric // for the top level region. 6280b57cec5SDimitry Andric MachineBasicBlock *Exit = initializeMRT(MF, RegionInfo, RegionMap); 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric unsigned BBSelectRegIn = createBBSelectReg(TII, MRI); 6310b57cec5SDimitry Andric MBBMRT *ExitMRT = new MBBMRT(Exit); 6320b57cec5SDimitry Andric RegionMap[RegionInfo->getRegionFor(Exit)]->addChild(ExitMRT); 6330b57cec5SDimitry Andric ExitMRT->setBBSelectRegIn(BBSelectRegIn); 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric for (auto MBBI : post_order(&(MF.front()))) { 6360b57cec5SDimitry Andric MachineBasicBlock *MBB = &(*MBBI); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric // Skip Exit since we already added it 6390b57cec5SDimitry Andric if (MBB == Exit) { 6400b57cec5SDimitry Andric continue; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting " << printMBBReference(*MBB) << "\n"); 6440b57cec5SDimitry Andric MBBMRT *NewMBB = new MBBMRT(MBB); 6450b57cec5SDimitry Andric MachineRegion *Region = RegionInfo->getRegionFor(MBB); 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric // Ensure we have the MRT region 6480b57cec5SDimitry Andric if (RegionMap.count(Region) == 0) { 6490b57cec5SDimitry Andric RegionMRT *NewMRTRegion = new RegionMRT(Region); 6500b57cec5SDimitry Andric RegionMap[Region] = NewMRTRegion; 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // Ensure all parents are in the RegionMap 6530b57cec5SDimitry Andric MachineRegion *Parent = Region->getParent(); 6540b57cec5SDimitry Andric while (RegionMap.count(Parent) == 0) { 6550b57cec5SDimitry Andric RegionMRT *NewMRTParent = new RegionMRT(Parent); 6560b57cec5SDimitry Andric NewMRTParent->addChild(NewMRTRegion); 6570b57cec5SDimitry Andric NewMRTRegion->setParent(NewMRTParent); 6580b57cec5SDimitry Andric RegionMap[Parent] = NewMRTParent; 6590b57cec5SDimitry Andric NewMRTRegion = NewMRTParent; 6600b57cec5SDimitry Andric Parent = Parent->getParent(); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric RegionMap[Parent]->addChild(NewMRTRegion); 6630b57cec5SDimitry Andric NewMRTRegion->setParent(RegionMap[Parent]); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // Add MBB to Region MRT 6670b57cec5SDimitry Andric RegionMap[Region]->addChild(NewMBB); 6680b57cec5SDimitry Andric NewMBB->setParent(RegionMap[Region]); 6690b57cec5SDimitry Andric RegionMap[Region]->setSucc(Region->getExit()); 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric return Result; 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 674e8d8bef9SDimitry Andric void LinearizedRegion::storeLiveOutReg(MachineBasicBlock *MBB, Register Reg, 6750b57cec5SDimitry Andric MachineInstr *DefInstr, 6760b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 6770b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 6780b57cec5SDimitry Andric PHILinearize &PHIInfo) { 679e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 6800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI) 6810b57cec5SDimitry Andric << "\n"); 6820b57cec5SDimitry Andric // If this is a source register to a PHI we are chaining, it 6830b57cec5SDimitry Andric // must be live out. 6840b57cec5SDimitry Andric if (PHIInfo.isSource(Reg)) { 6850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (PHI): " << printReg(Reg, TRI) << "\n"); 6860b57cec5SDimitry Andric addLiveOut(Reg); 6870b57cec5SDimitry Andric } else { 6880b57cec5SDimitry Andric // If this is live out of the MBB 6890b57cec5SDimitry Andric for (auto &UI : MRI->use_operands(Reg)) { 6900b57cec5SDimitry Andric if (UI.getParent()->getParent() != MBB) { 6910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (MBB " << printMBBReference(*MBB) 6920b57cec5SDimitry Andric << "): " << printReg(Reg, TRI) << "\n"); 6930b57cec5SDimitry Andric addLiveOut(Reg); 6940b57cec5SDimitry Andric } else { 6950b57cec5SDimitry Andric // If the use is in the same MBB we have to make sure 6960b57cec5SDimitry Andric // it is after the def, otherwise it is live out in a loop 6970b57cec5SDimitry Andric MachineInstr *UseInstr = UI.getParent(); 6980b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator 6990b57cec5SDimitry Andric MII = UseInstr->getIterator(), 7000b57cec5SDimitry Andric MIE = UseInstr->getParent()->instr_end(); 7010b57cec5SDimitry Andric MII != MIE; ++MII) { 7020b57cec5SDimitry Andric if ((&(*MII)) == DefInstr) { 7030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Loop): " << printReg(Reg, TRI) 7040b57cec5SDimitry Andric << "\n"); 7050b57cec5SDimitry Andric addLiveOut(Reg); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric 714e8d8bef9SDimitry Andric void LinearizedRegion::storeLiveOutRegRegion(RegionMRT *Region, Register Reg, 7150b57cec5SDimitry Andric MachineInstr *DefInstr, 7160b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7170b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7180b57cec5SDimitry Andric PHILinearize &PHIInfo) { 719e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 7200b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI) 7210b57cec5SDimitry Andric << "\n"); 7220b57cec5SDimitry Andric for (auto &UI : MRI->use_operands(Reg)) { 7230b57cec5SDimitry Andric if (!Region->contains(UI.getParent()->getParent())) { 7240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Region " << (void *)Region 7250b57cec5SDimitry Andric << "): " << printReg(Reg, TRI) << "\n"); 7260b57cec5SDimitry Andric addLiveOut(Reg); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric void LinearizedRegion::storeLiveOuts(MachineBasicBlock *MBB, 7330b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7340b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7350b57cec5SDimitry Andric PHILinearize &PHIInfo) { 7360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Begin (" << printMBBReference(*MBB) 7370b57cec5SDimitry Andric << ")-\n"); 7380b57cec5SDimitry Andric for (auto &II : *MBB) { 7390b57cec5SDimitry Andric for (auto &RI : II.defs()) { 7400b57cec5SDimitry Andric storeLiveOutReg(MBB, RI.getReg(), RI.getParent(), MRI, TRI, PHIInfo); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric for (auto &IRI : II.implicit_operands()) { 7430b57cec5SDimitry Andric if (IRI.isDef()) { 7440b57cec5SDimitry Andric storeLiveOutReg(MBB, IRI.getReg(), IRI.getParent(), MRI, TRI, PHIInfo); 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric // If we have a successor with a PHI, source coming from this MBB we have to 7500b57cec5SDimitry Andric // add the register as live out 751*349cc55cSDimitry Andric for (MachineBasicBlock *Succ : MBB->successors()) { 752*349cc55cSDimitry Andric for (auto &II : *Succ) { 7530b57cec5SDimitry Andric if (II.isPHI()) { 7540b57cec5SDimitry Andric MachineInstr &PHI = II; 7550b57cec5SDimitry Andric int numPreds = getPHINumInputs(PHI); 7560b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 7570b57cec5SDimitry Andric if (getPHIPred(PHI, i) == MBB) { 7580b57cec5SDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i); 7590b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 7600b57cec5SDimitry Andric << "Add LiveOut (PhiSource " << printMBBReference(*MBB) 761*349cc55cSDimitry Andric << " -> " << printMBBReference(*Succ) 7620b57cec5SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n"); 7630b57cec5SDimitry Andric addLiveOut(PHIReg); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Endn-\n"); 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric void LinearizedRegion::storeMBBLiveOuts(MachineBasicBlock *MBB, 7740b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7750b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7760b57cec5SDimitry Andric PHILinearize &PHIInfo, 7770b57cec5SDimitry Andric RegionMRT *TopRegion) { 7780b57cec5SDimitry Andric for (auto &II : *MBB) { 7790b57cec5SDimitry Andric for (auto &RI : II.defs()) { 7800b57cec5SDimitry Andric storeLiveOutRegRegion(TopRegion, RI.getReg(), RI.getParent(), MRI, TRI, 7810b57cec5SDimitry Andric PHIInfo); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric for (auto &IRI : II.implicit_operands()) { 7840b57cec5SDimitry Andric if (IRI.isDef()) { 7850b57cec5SDimitry Andric storeLiveOutRegRegion(TopRegion, IRI.getReg(), IRI.getParent(), MRI, 7860b57cec5SDimitry Andric TRI, PHIInfo); 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric void LinearizedRegion::storeLiveOuts(RegionMRT *Region, 7930b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 7940b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7950b57cec5SDimitry Andric PHILinearize &PHIInfo, 7960b57cec5SDimitry Andric RegionMRT *CurrentTopRegion) { 7970b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getSucc(); 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric RegionMRT *TopRegion = 8000b57cec5SDimitry Andric CurrentTopRegion == nullptr ? Region : CurrentTopRegion; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric // Check if exit is end of function, if so, no live outs. 8030b57cec5SDimitry Andric if (Exit == nullptr) 8040b57cec5SDimitry Andric return; 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric auto Children = Region->getChildren(); 8070b57cec5SDimitry Andric for (auto CI : *Children) { 8080b57cec5SDimitry Andric if (CI->isMBB()) { 8090b57cec5SDimitry Andric auto MBB = CI->getMBBMRT()->getMBB(); 8100b57cec5SDimitry Andric storeMBBLiveOuts(MBB, MRI, TRI, PHIInfo, TopRegion); 8110b57cec5SDimitry Andric } else { 8120b57cec5SDimitry Andric LinearizedRegion *SubRegion = CI->getRegionMRT()->getLinearizedRegion(); 8130b57cec5SDimitry Andric // We should be limited to only store registers that are live out from the 814*349cc55cSDimitry Andric // linearized region 8150b57cec5SDimitry Andric for (auto MBBI : SubRegion->MBBs) { 8160b57cec5SDimitry Andric storeMBBLiveOuts(MBBI, MRI, TRI, PHIInfo, TopRegion); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric if (CurrentTopRegion == nullptr) { 8220b57cec5SDimitry Andric auto Succ = Region->getSucc(); 8230b57cec5SDimitry Andric for (auto &II : *Succ) { 8240b57cec5SDimitry Andric if (II.isPHI()) { 8250b57cec5SDimitry Andric MachineInstr &PHI = II; 8260b57cec5SDimitry Andric int numPreds = getPHINumInputs(PHI); 8270b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 8280b57cec5SDimitry Andric if (Region->contains(getPHIPred(PHI, i))) { 8290b57cec5SDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i); 8300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add Region LiveOut (" << (void *)Region 8310b57cec5SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n"); 8320b57cec5SDimitry Andric addLiveOut(PHIReg); 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric #ifndef NDEBUG 8410b57cec5SDimitry Andric void LinearizedRegion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { 8420b57cec5SDimitry Andric OS << "Linearized Region {"; 8430b57cec5SDimitry Andric bool IsFirst = true; 844480093f4SDimitry Andric for (auto MBB : MBBs) { 8450b57cec5SDimitry Andric if (IsFirst) { 8460b57cec5SDimitry Andric IsFirst = false; 8470b57cec5SDimitry Andric } else { 8480b57cec5SDimitry Andric OS << " ,"; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric OS << MBB->getNumber(); 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric OS << "} (" << Entry->getNumber() << ", " 8530b57cec5SDimitry Andric << (Exit == nullptr ? -1 : Exit->getNumber()) 8540b57cec5SDimitry Andric << "): In:" << printReg(getBBSelectRegIn(), TRI) 8550b57cec5SDimitry Andric << " Out:" << printReg(getBBSelectRegOut(), TRI) << " {"; 8560b57cec5SDimitry Andric for (auto &LI : LiveOuts) { 8570b57cec5SDimitry Andric OS << printReg(LI, TRI) << " "; 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric OS << "} \n"; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric #endif 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric unsigned LinearizedRegion::getBBSelectRegIn() { 8640b57cec5SDimitry Andric return getRegionMRT()->getBBSelectRegIn(); 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric unsigned LinearizedRegion::getBBSelectRegOut() { 8680b57cec5SDimitry Andric return getRegionMRT()->getBBSelectRegOut(); 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric void LinearizedRegion::setHasLoop(bool Value) { HasLoop = Value; } 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric bool LinearizedRegion::getHasLoop() { return HasLoop; } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric void LinearizedRegion::addLiveOut(unsigned VReg) { LiveOuts.insert(VReg); } 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric void LinearizedRegion::removeLiveOut(unsigned Reg) { 8780b57cec5SDimitry Andric if (isLiveOut(Reg)) 8790b57cec5SDimitry Andric LiveOuts.erase(Reg); 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric void LinearizedRegion::replaceLiveOut(unsigned OldReg, unsigned NewReg) { 8830b57cec5SDimitry Andric if (isLiveOut(OldReg)) { 8840b57cec5SDimitry Andric removeLiveOut(OldReg); 8850b57cec5SDimitry Andric addLiveOut(NewReg); 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 889e8d8bef9SDimitry Andric void LinearizedRegion::replaceRegister(unsigned Register, 890e8d8bef9SDimitry Andric class Register NewRegister, 8910b57cec5SDimitry Andric MachineRegisterInfo *MRI, 8920b57cec5SDimitry Andric bool ReplaceInside, bool ReplaceOutside, 8930b57cec5SDimitry Andric bool IncludeLoopPHI) { 8940b57cec5SDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself"); 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric LLVM_DEBUG( 897*349cc55cSDimitry Andric dbgs() << "Preparing to replace register (region): " 8980b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) << " with " 8990b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) << "\n"); 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric // If we are replacing outside, we also need to update the LiveOuts 9020b57cec5SDimitry Andric if (ReplaceOutside && 9030b57cec5SDimitry Andric (isLiveOut(Register) || this->getParent()->isLiveOut(Register))) { 9040b57cec5SDimitry Andric LinearizedRegion *Current = this; 9050b57cec5SDimitry Andric while (Current != nullptr && Current->getEntry() != nullptr) { 9060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Region before register replace\n"); 9070b57cec5SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 9080b57cec5SDimitry Andric Current->replaceLiveOut(Register, NewRegister); 9090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Region after register replace\n"); 9100b57cec5SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo())); 9110b57cec5SDimitry Andric Current = Current->getParent(); 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 9160b57cec5SDimitry Andric E = MRI->reg_end(); 9170b57cec5SDimitry Andric I != E;) { 9180b57cec5SDimitry Andric MachineOperand &O = *I; 9190b57cec5SDimitry Andric ++I; 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric // We don't rewrite defs. 9220b57cec5SDimitry Andric if (O.isDef()) 9230b57cec5SDimitry Andric continue; 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric bool IsInside = contains(O.getParent()->getParent()); 9260b57cec5SDimitry Andric bool IsLoopPHI = IsInside && (O.getParent()->isPHI() && 9270b57cec5SDimitry Andric O.getParent()->getParent() == getEntry()); 9280b57cec5SDimitry Andric bool ShouldReplace = (IsInside && ReplaceInside) || 9290b57cec5SDimitry Andric (!IsInside && ReplaceOutside) || 9300b57cec5SDimitry Andric (IncludeLoopPHI && IsLoopPHI); 9310b57cec5SDimitry Andric if (ShouldReplace) { 9320b57cec5SDimitry Andric 933e8d8bef9SDimitry Andric if (NewRegister.isPhysical()) { 9340b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: " 9350b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 9360b57cec5SDimitry Andric << "\n"); 9370b57cec5SDimitry Andric llvm_unreachable("Cannot substitute physical registers"); 9380b57cec5SDimitry Andric } else { 9390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register (region): " 9400b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) 9410b57cec5SDimitry Andric << " with " 9420b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 9430b57cec5SDimitry Andric << "\n"); 9440b57cec5SDimitry Andric O.setReg(NewRegister); 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric void LinearizedRegion::replaceRegisterInsideRegion(unsigned Register, 9510b57cec5SDimitry Andric unsigned NewRegister, 9520b57cec5SDimitry Andric bool IncludeLoopPHIs, 9530b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 9540b57cec5SDimitry Andric replaceRegister(Register, NewRegister, MRI, true, false, IncludeLoopPHIs); 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric void LinearizedRegion::replaceRegisterOutsideRegion(unsigned Register, 9580b57cec5SDimitry Andric unsigned NewRegister, 9590b57cec5SDimitry Andric bool IncludeLoopPHIs, 9600b57cec5SDimitry Andric MachineRegisterInfo *MRI) { 9610b57cec5SDimitry Andric replaceRegister(Register, NewRegister, MRI, false, true, IncludeLoopPHIs); 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric DenseSet<unsigned> *LinearizedRegion::getLiveOuts() { return &LiveOuts; } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric void LinearizedRegion::setEntry(MachineBasicBlock *NewEntry) { 9670b57cec5SDimitry Andric Entry = NewEntry; 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric MachineBasicBlock *LinearizedRegion::getEntry() { return Entry; } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric void LinearizedRegion::setExit(MachineBasicBlock *NewExit) { Exit = NewExit; } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric MachineBasicBlock *LinearizedRegion::getExit() { return Exit; } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric void LinearizedRegion::addMBB(MachineBasicBlock *MBB) { MBBs.insert(MBB); } 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric void LinearizedRegion::addMBBs(LinearizedRegion *InnerRegion) { 979480093f4SDimitry Andric for (auto MBB : InnerRegion->MBBs) { 9800b57cec5SDimitry Andric addMBB(MBB); 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric bool LinearizedRegion::contains(MachineBasicBlock *MBB) { 985e8d8bef9SDimitry Andric return MBBs.contains(MBB); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric bool LinearizedRegion::isLiveOut(unsigned Reg) { 989e8d8bef9SDimitry Andric return LiveOuts.contains(Reg); 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric bool LinearizedRegion::hasNoDef(unsigned Reg, MachineRegisterInfo *MRI) { 9930b57cec5SDimitry Andric return MRI->def_begin(Reg) == MRI->def_end(); 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // After the code has been structurized, what was flagged as kills 9970b57cec5SDimitry Andric // before are no longer register kills. 9980b57cec5SDimitry Andric void LinearizedRegion::removeFalseRegisterKills(MachineRegisterInfo *MRI) { 9990b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); 10008bcb0991SDimitry Andric (void)TRI; // It's used by LLVM_DEBUG. 10018bcb0991SDimitry Andric 10020b57cec5SDimitry Andric for (auto MBBI : MBBs) { 10030b57cec5SDimitry Andric MachineBasicBlock *MBB = MBBI; 10040b57cec5SDimitry Andric for (auto &II : *MBB) { 10050b57cec5SDimitry Andric for (auto &RI : II.uses()) { 10060b57cec5SDimitry Andric if (RI.isReg()) { 10078bcb0991SDimitry Andric Register Reg = RI.getReg(); 1008e8d8bef9SDimitry Andric if (Reg.isVirtual()) { 10090b57cec5SDimitry Andric if (hasNoDef(Reg, MRI)) 10100b57cec5SDimitry Andric continue; 10110b57cec5SDimitry Andric if (!MRI->hasOneDef(Reg)) { 10120b57cec5SDimitry Andric LLVM_DEBUG(this->getEntry()->getParent()->dump()); 10130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(Reg, TRI) << "\n"); 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) { 10170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 10180b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 10190b57cec5SDimitry Andric << " has NO defs\n"); 10200b57cec5SDimitry Andric } else if (!MRI->hasOneDef(Reg)) { 10210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 10220b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 10230b57cec5SDimitry Andric << " has multiple defs\n"); 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 10270b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(Reg))); 10280b57cec5SDimitry Andric MachineOperand *UseOperand = &(RI); 10290b57cec5SDimitry Andric bool UseIsOutsideDefMBB = Def->getParent()->getParent() != MBB; 10300b57cec5SDimitry Andric if (UseIsOutsideDefMBB && UseOperand->isKill()) { 10310b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Removing kill flag on register: " 10320b57cec5SDimitry Andric << printReg(Reg, TRI) << "\n"); 10330b57cec5SDimitry Andric UseOperand->setIsKill(false); 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric void LinearizedRegion::initLiveOut(RegionMRT *Region, 10430b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 10440b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 10450b57cec5SDimitry Andric PHILinearize &PHIInfo) { 10460b57cec5SDimitry Andric storeLiveOuts(Region, MRI, TRI, PHIInfo); 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric LinearizedRegion::LinearizedRegion(MachineBasicBlock *MBB, 10500b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 10510b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 10520b57cec5SDimitry Andric PHILinearize &PHIInfo) { 10530b57cec5SDimitry Andric setEntry(MBB); 10540b57cec5SDimitry Andric setExit(MBB); 10550b57cec5SDimitry Andric storeLiveOuts(MBB, MRI, TRI, PHIInfo); 10560b57cec5SDimitry Andric MBBs.insert(MBB); 10570b57cec5SDimitry Andric Parent = nullptr; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric LinearizedRegion::LinearizedRegion() { 10610b57cec5SDimitry Andric setEntry(nullptr); 10620b57cec5SDimitry Andric setExit(nullptr); 10630b57cec5SDimitry Andric Parent = nullptr; 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric namespace { 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric class AMDGPUMachineCFGStructurizer : public MachineFunctionPass { 10690b57cec5SDimitry Andric private: 10700b57cec5SDimitry Andric const MachineRegionInfo *Regions; 10710b57cec5SDimitry Andric const SIInstrInfo *TII; 10720b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 10730b57cec5SDimitry Andric MachineRegisterInfo *MRI; 10740b57cec5SDimitry Andric PHILinearize PHIInfo; 10750b57cec5SDimitry Andric DenseMap<MachineBasicBlock *, MachineBasicBlock *> FallthroughMap; 10760b57cec5SDimitry Andric RegionMRT *RMRT; 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric void getPHIRegionIndices(RegionMRT *Region, MachineInstr &PHI, 10790b57cec5SDimitry Andric SmallVector<unsigned, 2> &RegionIndices); 10800b57cec5SDimitry Andric void getPHIRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 10810b57cec5SDimitry Andric SmallVector<unsigned, 2> &RegionIndices); 10820b57cec5SDimitry Andric void getPHINonRegionIndices(LinearizedRegion *Region, MachineInstr &PHI, 10830b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices); 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric void storePHILinearizationInfoDest( 10860b57cec5SDimitry Andric unsigned LDestReg, MachineInstr &PHI, 10870b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices = nullptr); 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric unsigned storePHILinearizationInfo(MachineInstr &PHI, 10900b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric void extractKilledPHIs(MachineBasicBlock *MBB); 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric bool shrinkPHI(MachineInstr &PHI, SmallVector<unsigned, 2> &PHIIndices, 10950b57cec5SDimitry Andric unsigned *ReplaceReg); 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric bool shrinkPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 10980b57cec5SDimitry Andric MachineBasicBlock *SourceMBB, 10990b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, unsigned *ReplaceReg); 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric void replacePHI(MachineInstr &PHI, unsigned CombinedSourceReg, 11020b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 11030b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices); 11040b57cec5SDimitry Andric void replaceEntryPHI(MachineInstr &PHI, unsigned CombinedSourceReg, 11050b57cec5SDimitry Andric MachineBasicBlock *IfMBB, 11060b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices); 11070b57cec5SDimitry Andric void replaceLiveOutRegs(MachineInstr &PHI, 11080b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices, 11090b57cec5SDimitry Andric unsigned CombinedSourceReg, 11100b57cec5SDimitry Andric LinearizedRegion *LRegion); 11110b57cec5SDimitry Andric void rewriteRegionExitPHI(RegionMRT *Region, MachineBasicBlock *LastMerge, 11120b57cec5SDimitry Andric MachineInstr &PHI, LinearizedRegion *LRegion); 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric void rewriteRegionExitPHIs(RegionMRT *Region, MachineBasicBlock *LastMerge, 11150b57cec5SDimitry Andric LinearizedRegion *LRegion); 11160b57cec5SDimitry Andric void rewriteRegionEntryPHI(LinearizedRegion *Region, MachineBasicBlock *IfMBB, 11170b57cec5SDimitry Andric MachineInstr &PHI); 11180b57cec5SDimitry Andric void rewriteRegionEntryPHIs(LinearizedRegion *Region, 11190b57cec5SDimitry Andric MachineBasicBlock *IfMBB); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric bool regionIsSimpleIf(RegionMRT *Region); 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric void transformSimpleIfRegion(RegionMRT *Region); 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric void insertUnconditionalBranch(MachineBasicBlock *MBB, 11260b57cec5SDimitry Andric MachineBasicBlock *Dest, 11270b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc()); 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric MachineBasicBlock *createLinearizedExitBlock(RegionMRT *Region); 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric void insertMergePHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11320b57cec5SDimitry Andric MachineBasicBlock *MergeBB, unsigned DestRegister, 11330b57cec5SDimitry Andric unsigned IfSourceRegister, unsigned CodeSourceRegister, 11340b57cec5SDimitry Andric bool IsUndefIfSource = false); 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric MachineBasicBlock *createIfBlock(MachineBasicBlock *MergeBB, 11370b57cec5SDimitry Andric MachineBasicBlock *CodeBBStart, 11380b57cec5SDimitry Andric MachineBasicBlock *CodeBBEnd, 11390b57cec5SDimitry Andric MachineBasicBlock *SelectBB, unsigned IfReg, 11400b57cec5SDimitry Andric bool InheritPreds); 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric void prunePHIInfo(MachineBasicBlock *MBB); 11430b57cec5SDimitry Andric void createEntryPHI(LinearizedRegion *CurrentRegion, unsigned DestReg); 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric void createEntryPHIs(LinearizedRegion *CurrentRegion); 11460b57cec5SDimitry Andric void resolvePHIInfos(MachineBasicBlock *FunctionEntry); 11470b57cec5SDimitry Andric 1148e8d8bef9SDimitry Andric void replaceRegisterWith(unsigned Register, class Register NewRegister); 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric MachineBasicBlock *createIfRegion(MachineBasicBlock *MergeBB, 11510b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 11520b57cec5SDimitry Andric LinearizedRegion *LRegion, 11530b57cec5SDimitry Andric unsigned BBSelectRegIn, 11540b57cec5SDimitry Andric unsigned BBSelectRegOut); 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric MachineBasicBlock * 11570b57cec5SDimitry Andric createIfRegion(MachineBasicBlock *MergeMBB, LinearizedRegion *InnerRegion, 11580b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 11590b57cec5SDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut); 11600b57cec5SDimitry Andric void ensureCondIsNotKilled(SmallVector<MachineOperand, 1> Cond); 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric void rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 11630b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11640b57cec5SDimitry Andric unsigned BBSelectReg); 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric MachineInstr *getDefInstr(unsigned Reg); 11670b57cec5SDimitry Andric void insertChainedPHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11680b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11690b57cec5SDimitry Andric LinearizedRegion *InnerRegion, unsigned DestReg, 11700b57cec5SDimitry Andric unsigned SourceReg); 11710b57cec5SDimitry Andric bool containsDef(MachineBasicBlock *MBB, LinearizedRegion *InnerRegion, 11720b57cec5SDimitry Andric unsigned Register); 11730b57cec5SDimitry Andric void rewriteLiveOutRegs(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB, 11740b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 11750b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 11760b57cec5SDimitry Andric LinearizedRegion *LRegion); 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric void splitLoopPHI(MachineInstr &PHI, MachineBasicBlock *Entry, 11790b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, LinearizedRegion *LRegion); 11800b57cec5SDimitry Andric void splitLoopPHIs(MachineBasicBlock *Entry, MachineBasicBlock *EntrySucc, 11810b57cec5SDimitry Andric LinearizedRegion *LRegion); 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric MachineBasicBlock *splitExit(LinearizedRegion *LRegion); 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric MachineBasicBlock *splitEntry(LinearizedRegion *LRegion); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric LinearizedRegion *initLinearizedRegion(RegionMRT *Region); 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric bool structurizeComplexRegion(RegionMRT *Region); 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric bool structurizeRegion(RegionMRT *Region); 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric bool structurizeRegions(RegionMRT *Region, bool isTopRegion); 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric public: 11960b57cec5SDimitry Andric static char ID; 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer() : MachineFunctionPass(ID) { 11990b57cec5SDimitry Andric initializeAMDGPUMachineCFGStructurizerPass(*PassRegistry::getPassRegistry()); 12000b57cec5SDimitry Andric } 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 12030b57cec5SDimitry Andric AU.addRequired<MachineRegionInfoPass>(); 12040b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric void initFallthroughMap(MachineFunction &MF); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric void createLinearizedRegion(RegionMRT *Region, unsigned SelectOut); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric unsigned initializeSelectRegisters(MRT *MRT, unsigned ExistingExitReg, 12120b57cec5SDimitry Andric MachineRegisterInfo *MRI, 12130b57cec5SDimitry Andric const SIInstrInfo *TII); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric void setRegionMRT(RegionMRT *RegionTree) { RMRT = RegionTree; } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric RegionMRT *getRegionMRT() { return RMRT; } 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 12200b57cec5SDimitry Andric }; 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric } // end anonymous namespace 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric char AMDGPUMachineCFGStructurizer::ID = 0; 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::regionIsSimpleIf(RegionMRT *Region) { 12270b57cec5SDimitry Andric MachineBasicBlock *Entry = Region->getEntry(); 12280b57cec5SDimitry Andric MachineBasicBlock *Succ = Region->getSucc(); 12290b57cec5SDimitry Andric bool FoundBypass = false; 12300b57cec5SDimitry Andric bool FoundIf = false; 12310b57cec5SDimitry Andric 12320b57cec5SDimitry Andric if (Entry->succ_size() != 2) { 12330b57cec5SDimitry Andric return false; 12340b57cec5SDimitry Andric } 12350b57cec5SDimitry Andric 1236*349cc55cSDimitry Andric for (MachineBasicBlock *Current : Entry->successors()) { 12370b57cec5SDimitry Andric if (Current == Succ) { 12380b57cec5SDimitry Andric FoundBypass = true; 12390b57cec5SDimitry Andric } else if ((Current->succ_size() == 1) && 12400b57cec5SDimitry Andric *(Current->succ_begin()) == Succ) { 12410b57cec5SDimitry Andric FoundIf = true; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric 12450b57cec5SDimitry Andric return FoundIf && FoundBypass; 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::transformSimpleIfRegion(RegionMRT *Region) { 12490b57cec5SDimitry Andric MachineBasicBlock *Entry = Region->getEntry(); 12500b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getExit(); 12510b57cec5SDimitry Andric TII->convertNonUniformIfRegion(Entry, Exit); 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric static void fixMBBTerminator(MachineBasicBlock *MBB) { 12550b57cec5SDimitry Andric if (MBB->succ_size() == 1) { 12560b57cec5SDimitry Andric auto *Succ = *(MBB->succ_begin()); 12570b57cec5SDimitry Andric for (auto &TI : MBB->terminators()) { 12580b57cec5SDimitry Andric for (auto &UI : TI.uses()) { 12590b57cec5SDimitry Andric if (UI.isMBB() && UI.getMBB() != Succ) { 12600b57cec5SDimitry Andric UI.setMBB(Succ); 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric static void fixRegionTerminator(RegionMRT *Region) { 12680b57cec5SDimitry Andric MachineBasicBlock *InternalSucc = nullptr; 12690b57cec5SDimitry Andric MachineBasicBlock *ExternalSucc = nullptr; 12700b57cec5SDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion(); 12710b57cec5SDimitry Andric auto Exit = LRegion->getExit(); 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 2> Successors; 1274*349cc55cSDimitry Andric for (MachineBasicBlock *Succ : Exit->successors()) { 12750b57cec5SDimitry Andric if (LRegion->contains(Succ)) { 12760b57cec5SDimitry Andric // Do not allow re-assign 12770b57cec5SDimitry Andric assert(InternalSucc == nullptr); 12780b57cec5SDimitry Andric InternalSucc = Succ; 12790b57cec5SDimitry Andric } else { 12800b57cec5SDimitry Andric // Do not allow re-assign 12810b57cec5SDimitry Andric assert(ExternalSucc == nullptr); 12820b57cec5SDimitry Andric ExternalSucc = Succ; 12830b57cec5SDimitry Andric } 12840b57cec5SDimitry Andric } 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric for (auto &TI : Exit->terminators()) { 12870b57cec5SDimitry Andric for (auto &UI : TI.uses()) { 12880b57cec5SDimitry Andric if (UI.isMBB()) { 12890b57cec5SDimitry Andric auto Target = UI.getMBB(); 12900b57cec5SDimitry Andric if (Target != InternalSucc && Target != ExternalSucc) { 12910b57cec5SDimitry Andric UI.setMBB(ExternalSucc); 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric } 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric // If a region region is just a sequence of regions (and the exit 12990b57cec5SDimitry Andric // block in the case of the top level region), we can simply skip 13000b57cec5SDimitry Andric // linearizing it, because it is already linear 13010b57cec5SDimitry Andric bool regionIsSequence(RegionMRT *Region) { 13020b57cec5SDimitry Andric auto Children = Region->getChildren(); 13030b57cec5SDimitry Andric for (auto CI : *Children) { 13040b57cec5SDimitry Andric if (!CI->isRegion()) { 13050b57cec5SDimitry Andric if (CI->getMBBMRT()->getMBB()->succ_size() > 1) { 13060b57cec5SDimitry Andric return false; 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric return true; 13110b57cec5SDimitry Andric } 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric void fixupRegionExits(RegionMRT *Region) { 13140b57cec5SDimitry Andric auto Children = Region->getChildren(); 13150b57cec5SDimitry Andric for (auto CI : *Children) { 13160b57cec5SDimitry Andric if (!CI->isRegion()) { 13170b57cec5SDimitry Andric fixMBBTerminator(CI->getMBBMRT()->getMBB()); 13180b57cec5SDimitry Andric } else { 13190b57cec5SDimitry Andric fixRegionTerminator(CI->getRegionMRT()); 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric } 13230b57cec5SDimitry Andric 13240b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 13250b57cec5SDimitry Andric RegionMRT *Region, MachineInstr &PHI, 13260b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 13270b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13280b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13290b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13300b57cec5SDimitry Andric if (Region->contains(Pred)) { 13310b57cec5SDimitry Andric PHIRegionIndices.push_back(i); 13320b57cec5SDimitry Andric } 13330b57cec5SDimitry Andric } 13340b57cec5SDimitry Andric } 13350b57cec5SDimitry Andric 13360b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices( 13370b57cec5SDimitry Andric LinearizedRegion *Region, MachineInstr &PHI, 13380b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 13390b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13400b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13410b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13420b57cec5SDimitry Andric if (Region->contains(Pred)) { 13430b57cec5SDimitry Andric PHIRegionIndices.push_back(i); 13440b57cec5SDimitry Andric } 13450b57cec5SDimitry Andric } 13460b57cec5SDimitry Andric } 13470b57cec5SDimitry Andric 13480b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::getPHINonRegionIndices( 13490b57cec5SDimitry Andric LinearizedRegion *Region, MachineInstr &PHI, 13500b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices) { 13510b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13520b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13530b57cec5SDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i); 13540b57cec5SDimitry Andric if (!Region->contains(Pred)) { 13550b57cec5SDimitry Andric PHINonRegionIndices.push_back(i); 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric } 13580b57cec5SDimitry Andric } 13590b57cec5SDimitry Andric 13600b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::storePHILinearizationInfoDest( 13610b57cec5SDimitry Andric unsigned LDestReg, MachineInstr &PHI, 13620b57cec5SDimitry Andric SmallVector<unsigned, 2> *RegionIndices) { 13630b57cec5SDimitry Andric if (RegionIndices) { 13640b57cec5SDimitry Andric for (auto i : *RegionIndices) { 13650b57cec5SDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 13660b57cec5SDimitry Andric } 13670b57cec5SDimitry Andric } else { 13680b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 13690b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 13700b57cec5SDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i)); 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric } 13730b57cec5SDimitry Andric } 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric unsigned AMDGPUMachineCFGStructurizer::storePHILinearizationInfo( 13760b57cec5SDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> *RegionIndices) { 13770b57cec5SDimitry Andric unsigned DestReg = getPHIDestReg(PHI); 13788bcb0991SDimitry Andric Register LinearizeDestReg = 13790b57cec5SDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(DestReg)); 13800b57cec5SDimitry Andric PHIInfo.addDest(LinearizeDestReg, PHI.getDebugLoc()); 13810b57cec5SDimitry Andric storePHILinearizationInfoDest(LinearizeDestReg, PHI, RegionIndices); 13820b57cec5SDimitry Andric return LinearizeDestReg; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::extractKilledPHIs(MachineBasicBlock *MBB) { 13860b57cec5SDimitry Andric // We need to create a new chain for the killed phi, but there is no 13870b57cec5SDimitry Andric // need to do the renaming outside or inside the block. 13880b57cec5SDimitry Andric SmallPtrSet<MachineInstr *, 2> PHIs; 13890b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), 13900b57cec5SDimitry Andric E = MBB->instr_end(); 13910b57cec5SDimitry Andric I != E; ++I) { 13920b57cec5SDimitry Andric MachineInstr &Instr = *I; 13930b57cec5SDimitry Andric if (Instr.isPHI()) { 13940b57cec5SDimitry Andric unsigned PHIDestReg = getPHIDestReg(Instr); 1395*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Extracting killed phi:\n"); 13960b57cec5SDimitry Andric LLVM_DEBUG(Instr.dump()); 13970b57cec5SDimitry Andric PHIs.insert(&Instr); 13980b57cec5SDimitry Andric PHIInfo.addDest(PHIDestReg, Instr.getDebugLoc()); 13990b57cec5SDimitry Andric storePHILinearizationInfoDest(PHIDestReg, Instr); 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric for (auto PI : PHIs) { 14040b57cec5SDimitry Andric PI->eraseFromParent(); 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric } 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric static bool isPHIRegionIndex(SmallVector<unsigned, 2> PHIRegionIndices, 14090b57cec5SDimitry Andric unsigned Index) { 1410fe6060f1SDimitry Andric return llvm::is_contained(PHIRegionIndices, Index); 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 14140b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, 14150b57cec5SDimitry Andric unsigned *ReplaceReg) { 14160b57cec5SDimitry Andric return shrinkPHI(PHI, 0, nullptr, PHIIndices, ReplaceReg); 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI, 14200b57cec5SDimitry Andric unsigned CombinedSourceReg, 14210b57cec5SDimitry Andric MachineBasicBlock *SourceMBB, 14220b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIIndices, 14230b57cec5SDimitry Andric unsigned *ReplaceReg) { 14240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Shrink PHI: "); 14250b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 14260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " to " << printReg(getPHIDestReg(PHI), TRI) 14270b57cec5SDimitry Andric << " = PHI("); 14280b57cec5SDimitry Andric 14290b57cec5SDimitry Andric bool Replaced = false; 14300b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 14310b57cec5SDimitry Andric int SingleExternalEntryIndex = -1; 14320b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14330b57cec5SDimitry Andric if (!isPHIRegionIndex(PHIIndices, i)) { 14340b57cec5SDimitry Andric if (SingleExternalEntryIndex == -1) { 14350b57cec5SDimitry Andric // Single entry 14360b57cec5SDimitry Andric SingleExternalEntryIndex = i; 14370b57cec5SDimitry Andric } else { 14380b57cec5SDimitry Andric // Multiple entries 14390b57cec5SDimitry Andric SingleExternalEntryIndex = -2; 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric } 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric if (SingleExternalEntryIndex > -1) { 14450b57cec5SDimitry Andric *ReplaceReg = getPHISourceReg(PHI, SingleExternalEntryIndex); 14460b57cec5SDimitry Andric // We should not rewrite the code, we should only pick up the single value 14470b57cec5SDimitry Andric // that represents the shrunk PHI. 14480b57cec5SDimitry Andric Replaced = true; 14490b57cec5SDimitry Andric } else { 14500b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 14510b57cec5SDimitry Andric MachineInstrBuilder MIB = 14520b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 14530b57cec5SDimitry Andric getPHIDestReg(PHI)); 14540b57cec5SDimitry Andric if (SourceMBB) { 14550b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 14560b57cec5SDimitry Andric MIB.addMBB(SourceMBB); 14570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 14580b57cec5SDimitry Andric << printMBBReference(*SourceMBB)); 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric 14610b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14620b57cec5SDimitry Andric if (isPHIRegionIndex(PHIIndices, i)) { 14630b57cec5SDimitry Andric continue; 14640b57cec5SDimitry Andric } 14650b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 14660b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 14670b57cec5SDimitry Andric MIB.addReg(SourceReg); 14680b57cec5SDimitry Andric MIB.addMBB(SourcePred); 14690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 14700b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric PHI.eraseFromParent(); 14750b57cec5SDimitry Andric return Replaced; 14760b57cec5SDimitry Andric } 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replacePHI( 14790b57cec5SDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *LastMerge, 14800b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 14810b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replace PHI: "); 14820b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 14830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " with " << printReg(getPHIDestReg(PHI), TRI) 14840b57cec5SDimitry Andric << " = PHI("); 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric bool HasExternalEdge = false; 14870b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 14880b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 14890b57cec5SDimitry Andric if (!isPHIRegionIndex(PHIRegionIndices, i)) { 14900b57cec5SDimitry Andric HasExternalEdge = true; 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric } 14930b57cec5SDimitry Andric 14940b57cec5SDimitry Andric if (HasExternalEdge) { 14950b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 14960b57cec5SDimitry Andric MachineInstrBuilder MIB = 14970b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 14980b57cec5SDimitry Andric getPHIDestReg(PHI)); 14990b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 15000b57cec5SDimitry Andric MIB.addMBB(LastMerge); 15010b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 15020b57cec5SDimitry Andric << printMBBReference(*LastMerge)); 15030b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15040b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15050b57cec5SDimitry Andric continue; 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 15080b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 15090b57cec5SDimitry Andric MIB.addReg(SourceReg); 15100b57cec5SDimitry Andric MIB.addMBB(SourcePred); 15110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 15120b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 15150b57cec5SDimitry Andric } else { 15160b57cec5SDimitry Andric replaceRegisterWith(getPHIDestReg(PHI), CombinedSourceReg); 15170b57cec5SDimitry Andric } 15180b57cec5SDimitry Andric PHI.eraseFromParent(); 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric 15210b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceEntryPHI( 15220b57cec5SDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *IfMBB, 15230b57cec5SDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) { 15240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replace entry PHI: "); 15250b57cec5SDimitry Andric LLVM_DEBUG(PHI.dump()); 15260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " with "); 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 15290b57cec5SDimitry Andric unsigned NumNonRegionInputs = NumInputs; 15300b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15310b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15320b57cec5SDimitry Andric NumNonRegionInputs--; 15330b57cec5SDimitry Andric } 15340b57cec5SDimitry Andric } 15350b57cec5SDimitry Andric 15360b57cec5SDimitry Andric if (NumNonRegionInputs == 0) { 15370b57cec5SDimitry Andric auto DestReg = getPHIDestReg(PHI); 15380b57cec5SDimitry Andric replaceRegisterWith(DestReg, CombinedSourceReg); 15390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " register " << printReg(CombinedSourceReg, TRI) 15400b57cec5SDimitry Andric << "\n"); 15410b57cec5SDimitry Andric PHI.eraseFromParent(); 15420b57cec5SDimitry Andric } else { 15430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(getPHIDestReg(PHI), TRI) << " = PHI("); 15440b57cec5SDimitry Andric MachineBasicBlock *MBB = PHI.getParent(); 15450b57cec5SDimitry Andric MachineInstrBuilder MIB = 15460b57cec5SDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI), 15470b57cec5SDimitry Andric getPHIDestReg(PHI)); 15480b57cec5SDimitry Andric MIB.addReg(CombinedSourceReg); 15490b57cec5SDimitry Andric MIB.addMBB(IfMBB); 15500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", " 15510b57cec5SDimitry Andric << printMBBReference(*IfMBB)); 15520b57cec5SDimitry Andric unsigned NumInputs = getPHINumInputs(PHI); 15530b57cec5SDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) { 15540b57cec5SDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) { 15550b57cec5SDimitry Andric continue; 15560b57cec5SDimitry Andric } 15570b57cec5SDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i); 15580b57cec5SDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i); 15590b57cec5SDimitry Andric MIB.addReg(SourceReg); 15600b57cec5SDimitry Andric MIB.addMBB(SourcePred); 15610b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 15620b57cec5SDimitry Andric << printMBBReference(*SourcePred)); 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 15650b57cec5SDimitry Andric PHI.eraseFromParent(); 15660b57cec5SDimitry Andric } 15670b57cec5SDimitry Andric } 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceLiveOutRegs( 15700b57cec5SDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> &PHIRegionIndices, 15710b57cec5SDimitry Andric unsigned CombinedSourceReg, LinearizedRegion *LRegion) { 15720b57cec5SDimitry Andric bool WasLiveOut = false; 15730b57cec5SDimitry Andric for (auto PII : PHIRegionIndices) { 15740b57cec5SDimitry Andric unsigned Reg = getPHISourceReg(PHI, PII); 15750b57cec5SDimitry Andric if (LRegion->isLiveOut(Reg)) { 15760b57cec5SDimitry Andric bool IsDead = true; 15770b57cec5SDimitry Andric 15780b57cec5SDimitry Andric // Check if register is live out of the basic block 15790b57cec5SDimitry Andric MachineBasicBlock *DefMBB = getDefInstr(Reg)->getParent(); 1580*349cc55cSDimitry Andric for (const MachineOperand &MO : MRI->use_operands(Reg)) 1581*349cc55cSDimitry Andric if (MO.getParent()->getParent() != DefMBB) 15820b57cec5SDimitry Andric IsDead = false; 15830b57cec5SDimitry Andric 15840b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " << printReg(Reg, TRI) << " is " 15850b57cec5SDimitry Andric << (IsDead ? "dead" : "alive") 15860b57cec5SDimitry Andric << " after PHI replace\n"); 15870b57cec5SDimitry Andric if (IsDead) { 15880b57cec5SDimitry Andric LRegion->removeLiveOut(Reg); 15890b57cec5SDimitry Andric } 15900b57cec5SDimitry Andric WasLiveOut = true; 15910b57cec5SDimitry Andric } 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric if (WasLiveOut) 15950b57cec5SDimitry Andric LRegion->addLiveOut(CombinedSourceReg); 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHI(RegionMRT *Region, 15990b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 16000b57cec5SDimitry Andric MachineInstr &PHI, 16010b57cec5SDimitry Andric LinearizedRegion *LRegion) { 16020b57cec5SDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices; 16030b57cec5SDimitry Andric getPHIRegionIndices(Region, PHI, PHIRegionIndices); 16040b57cec5SDimitry Andric unsigned LinearizedSourceReg = 16050b57cec5SDimitry Andric storePHILinearizationInfo(PHI, &PHIRegionIndices); 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric replacePHI(PHI, LinearizedSourceReg, LastMerge, PHIRegionIndices); 16080b57cec5SDimitry Andric replaceLiveOutRegs(PHI, PHIRegionIndices, LinearizedSourceReg, LRegion); 16090b57cec5SDimitry Andric } 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHI(LinearizedRegion *Region, 16120b57cec5SDimitry Andric MachineBasicBlock *IfMBB, 16130b57cec5SDimitry Andric MachineInstr &PHI) { 16140b57cec5SDimitry Andric SmallVector<unsigned, 2> PHINonRegionIndices; 16150b57cec5SDimitry Andric getPHINonRegionIndices(Region, PHI, PHINonRegionIndices); 16160b57cec5SDimitry Andric unsigned LinearizedSourceReg = 16170b57cec5SDimitry Andric storePHILinearizationInfo(PHI, &PHINonRegionIndices); 16180b57cec5SDimitry Andric replaceEntryPHI(PHI, LinearizedSourceReg, IfMBB, PHINonRegionIndices); 16190b57cec5SDimitry Andric } 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric static void collectPHIs(MachineBasicBlock *MBB, 16220b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> &PHIs) { 16230b57cec5SDimitry Andric for (auto &BBI : *MBB) { 16240b57cec5SDimitry Andric if (BBI.isPHI()) { 16250b57cec5SDimitry Andric PHIs.push_back(&BBI); 16260b57cec5SDimitry Andric } 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHIs(RegionMRT *Region, 16310b57cec5SDimitry Andric MachineBasicBlock *LastMerge, 16320b57cec5SDimitry Andric LinearizedRegion *LRegion) { 16330b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 16340b57cec5SDimitry Andric auto Exit = Region->getSucc(); 16350b57cec5SDimitry Andric if (Exit == nullptr) 16360b57cec5SDimitry Andric return; 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric collectPHIs(Exit, PHIs); 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric for (auto PHII : PHIs) { 16410b57cec5SDimitry Andric rewriteRegionExitPHI(Region, LastMerge, *PHII, LRegion); 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric } 16440b57cec5SDimitry Andric 16450b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHIs(LinearizedRegion *Region, 16460b57cec5SDimitry Andric MachineBasicBlock *IfMBB) { 16470b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 16480b57cec5SDimitry Andric auto Entry = Region->getEntry(); 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric collectPHIs(Entry, PHIs); 16510b57cec5SDimitry Andric 16520b57cec5SDimitry Andric for (auto PHII : PHIs) { 16530b57cec5SDimitry Andric rewriteRegionEntryPHI(Region, IfMBB, *PHII); 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric } 16560b57cec5SDimitry Andric 16570b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertUnconditionalBranch(MachineBasicBlock *MBB, 16580b57cec5SDimitry Andric MachineBasicBlock *Dest, 16590b57cec5SDimitry Andric const DebugLoc &DL) { 16600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting unconditional branch: " << MBB->getNumber() 16610b57cec5SDimitry Andric << " -> " << Dest->getNumber() << "\n"); 16620b57cec5SDimitry Andric MachineBasicBlock::instr_iterator Terminator = MBB->getFirstInstrTerminator(); 16630b57cec5SDimitry Andric bool HasTerminator = Terminator != MBB->instr_end(); 16640b57cec5SDimitry Andric if (HasTerminator) { 16650b57cec5SDimitry Andric TII->ReplaceTailWithBranchTo(Terminator, Dest); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(Dest)) { 16680b57cec5SDimitry Andric TII->insertUnconditionalBranch(*MBB, Dest, DL); 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric static MachineBasicBlock *getSingleExitNode(MachineFunction &MF) { 16730b57cec5SDimitry Andric MachineBasicBlock *result = nullptr; 16740b57cec5SDimitry Andric for (auto &MFI : MF) { 1675*349cc55cSDimitry Andric if (MFI.succ_empty()) { 16760b57cec5SDimitry Andric if (result == nullptr) { 16770b57cec5SDimitry Andric result = &MFI; 16780b57cec5SDimitry Andric } else { 16790b57cec5SDimitry Andric return nullptr; 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric } 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric 16840b57cec5SDimitry Andric return result; 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric static bool hasOneExitNode(MachineFunction &MF) { 16880b57cec5SDimitry Andric return getSingleExitNode(MF) != nullptr; 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric MachineBasicBlock * 16920b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::createLinearizedExitBlock(RegionMRT *Region) { 16930b57cec5SDimitry Andric auto Exit = Region->getSucc(); 16940b57cec5SDimitry Andric 16950b57cec5SDimitry Andric // If the exit is the end of the function, we just use the existing 16960b57cec5SDimitry Andric MachineFunction *MF = Region->getEntry()->getParent(); 16970b57cec5SDimitry Andric if (Exit == nullptr && hasOneExitNode(*MF)) { 16980b57cec5SDimitry Andric return &(*(--(Region->getEntry()->getParent()->end()))); 16990b57cec5SDimitry Andric } 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric MachineBasicBlock *LastMerge = MF->CreateMachineBasicBlock(); 17020b57cec5SDimitry Andric if (Exit == nullptr) { 17030b57cec5SDimitry Andric MachineFunction::iterator ExitIter = MF->end(); 17040b57cec5SDimitry Andric MF->insert(ExitIter, LastMerge); 17050b57cec5SDimitry Andric } else { 17060b57cec5SDimitry Andric MachineFunction::iterator ExitIter = Exit->getIterator(); 17070b57cec5SDimitry Andric MF->insert(ExitIter, LastMerge); 17080b57cec5SDimitry Andric LastMerge->addSuccessor(Exit); 17090b57cec5SDimitry Andric insertUnconditionalBranch(LastMerge, Exit); 17100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created exit block: " << LastMerge->getNumber() 17110b57cec5SDimitry Andric << "\n"); 17120b57cec5SDimitry Andric } 17130b57cec5SDimitry Andric return LastMerge; 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertMergePHI(MachineBasicBlock *IfBB, 17170b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 17180b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 17190b57cec5SDimitry Andric unsigned DestRegister, 17200b57cec5SDimitry Andric unsigned IfSourceRegister, 17210b57cec5SDimitry Andric unsigned CodeSourceRegister, 17220b57cec5SDimitry Andric bool IsUndefIfSource) { 17230b57cec5SDimitry Andric // If this is the function exit block, we don't need a phi. 17240b57cec5SDimitry Andric if (MergeBB->succ_begin() == MergeBB->succ_end()) { 17250b57cec5SDimitry Andric return; 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Merge PHI (" << printMBBReference(*MergeBB) 17280b57cec5SDimitry Andric << "): " << printReg(DestRegister, TRI) << " = PHI(" 17290b57cec5SDimitry Andric << printReg(IfSourceRegister, TRI) << ", " 17300b57cec5SDimitry Andric << printMBBReference(*IfBB) 17310b57cec5SDimitry Andric << printReg(CodeSourceRegister, TRI) << ", " 17320b57cec5SDimitry Andric << printMBBReference(*CodeBB) << ")\n"); 17330b57cec5SDimitry Andric const DebugLoc &DL = MergeBB->findDebugLoc(MergeBB->begin()); 17340b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*MergeBB, MergeBB->instr_begin(), DL, 17350b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), DestRegister); 17360b57cec5SDimitry Andric if (IsUndefIfSource && false) { 17370b57cec5SDimitry Andric MIB.addReg(IfSourceRegister, RegState::Undef); 17380b57cec5SDimitry Andric } else { 17390b57cec5SDimitry Andric MIB.addReg(IfSourceRegister); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric MIB.addMBB(IfBB); 17420b57cec5SDimitry Andric MIB.addReg(CodeSourceRegister); 17430b57cec5SDimitry Andric MIB.addMBB(CodeBB); 17440b57cec5SDimitry Andric } 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric static void removeExternalCFGSuccessors(MachineBasicBlock *MBB) { 17470b57cec5SDimitry Andric for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(), 17480b57cec5SDimitry Andric E = MBB->succ_end(); 17490b57cec5SDimitry Andric PI != E; ++PI) { 17500b57cec5SDimitry Andric if ((*PI) != MBB) { 17510b57cec5SDimitry Andric (MBB)->removeSuccessor(*PI); 17520b57cec5SDimitry Andric } 17530b57cec5SDimitry Andric } 17540b57cec5SDimitry Andric } 17550b57cec5SDimitry Andric 17560b57cec5SDimitry Andric static void removeExternalCFGEdges(MachineBasicBlock *StartMBB, 17570b57cec5SDimitry Andric MachineBasicBlock *EndMBB) { 17580b57cec5SDimitry Andric 1759*349cc55cSDimitry Andric // We have to check against the StartMBB successor because a 17600b57cec5SDimitry Andric // structurized region with a loop will have the entry block split, 17610b57cec5SDimitry Andric // and the backedge will go to the entry successor. 17620b57cec5SDimitry Andric DenseSet<std::pair<MachineBasicBlock *, MachineBasicBlock *>> Succs; 17630b57cec5SDimitry Andric unsigned SuccSize = StartMBB->succ_size(); 17640b57cec5SDimitry Andric if (SuccSize > 0) { 17650b57cec5SDimitry Andric MachineBasicBlock *StartMBBSucc = *(StartMBB->succ_begin()); 1766*349cc55cSDimitry Andric for (MachineBasicBlock *Succ : EndMBB->successors()) { 17670b57cec5SDimitry Andric // Either we have a back-edge to the entry block, or a back-edge to the 17680b57cec5SDimitry Andric // successor of the entry block since the block may be split. 1769*349cc55cSDimitry Andric if (Succ != StartMBB && 1770*349cc55cSDimitry Andric !(Succ == StartMBBSucc && StartMBB != EndMBB && SuccSize == 1)) { 17710b57cec5SDimitry Andric Succs.insert( 1772*349cc55cSDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *>(EndMBB, Succ)); 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric } 17750b57cec5SDimitry Andric } 17760b57cec5SDimitry Andric 1777*349cc55cSDimitry Andric for (MachineBasicBlock *Pred : StartMBB->predecessors()) 1778*349cc55cSDimitry Andric if (Pred != EndMBB) 1779*349cc55cSDimitry Andric Succs.insert(std::make_pair(Pred, StartMBB)); 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric for (auto SI : Succs) { 17820b57cec5SDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *> Edge = SI; 17830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Removing edge: " << printMBBReference(*Edge.first) 17840b57cec5SDimitry Andric << " -> " << printMBBReference(*Edge.second) << "\n"); 17850b57cec5SDimitry Andric Edge.first->removeSuccessor(Edge.second); 17860b57cec5SDimitry Andric } 17870b57cec5SDimitry Andric } 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfBlock( 17900b57cec5SDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBBStart, 17910b57cec5SDimitry Andric MachineBasicBlock *CodeBBEnd, MachineBasicBlock *SelectBB, unsigned IfReg, 17920b57cec5SDimitry Andric bool InheritPreds) { 17930b57cec5SDimitry Andric MachineFunction *MF = MergeBB->getParent(); 17940b57cec5SDimitry Andric MachineBasicBlock *IfBB = MF->CreateMachineBasicBlock(); 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric if (InheritPreds) { 1797*349cc55cSDimitry Andric for (MachineBasicBlock *Pred : CodeBBStart->predecessors()) 1798*349cc55cSDimitry Andric if (Pred != CodeBBEnd) 17990b57cec5SDimitry Andric Pred->addSuccessor(IfBB); 18000b57cec5SDimitry Andric } 18010b57cec5SDimitry Andric 18020b57cec5SDimitry Andric removeExternalCFGEdges(CodeBBStart, CodeBBEnd); 18030b57cec5SDimitry Andric 18040b57cec5SDimitry Andric auto CodeBBStartI = CodeBBStart->getIterator(); 18050b57cec5SDimitry Andric auto CodeBBEndI = CodeBBEnd->getIterator(); 18060b57cec5SDimitry Andric auto MergeIter = MergeBB->getIterator(); 18070b57cec5SDimitry Andric MF->insert(MergeIter, IfBB); 18080b57cec5SDimitry Andric MF->splice(MergeIter, CodeBBStartI, ++CodeBBEndI); 18090b57cec5SDimitry Andric IfBB->addSuccessor(MergeBB); 18100b57cec5SDimitry Andric IfBB->addSuccessor(CodeBBStart); 18110b57cec5SDimitry Andric 18120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created If block: " << IfBB->getNumber() << "\n"); 18130b57cec5SDimitry Andric // Ensure that the MergeBB is a successor of the CodeEndBB. 18140b57cec5SDimitry Andric if (!CodeBBEnd->isSuccessor(MergeBB)) 18150b57cec5SDimitry Andric CodeBBEnd->addSuccessor(MergeBB); 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Moved " << printMBBReference(*CodeBBStart) 18180b57cec5SDimitry Andric << " through " << printMBBReference(*CodeBBEnd) << "\n"); 18190b57cec5SDimitry Andric 18200b57cec5SDimitry Andric // If we have a single predecessor we can find a reasonable debug location 18210b57cec5SDimitry Andric MachineBasicBlock *SinglePred = 18220b57cec5SDimitry Andric CodeBBStart->pred_size() == 1 ? *(CodeBBStart->pred_begin()) : nullptr; 18230b57cec5SDimitry Andric const DebugLoc &DL = SinglePred 18240b57cec5SDimitry Andric ? SinglePred->findDebugLoc(SinglePred->getFirstTerminator()) 18250b57cec5SDimitry Andric : DebugLoc(); 18260b57cec5SDimitry Andric 1827e8d8bef9SDimitry Andric Register Reg = 18280b57cec5SDimitry Andric TII->insertEQ(IfBB, IfBB->begin(), DL, IfReg, 18290b57cec5SDimitry Andric SelectBB->getNumber() /* CodeBBStart->getNumber() */); 18300b57cec5SDimitry Andric if (&(*(IfBB->getParent()->begin())) == IfBB) { 18310b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->begin(), DL, IfReg, 18320b57cec5SDimitry Andric CodeBBStart->getNumber()); 18330b57cec5SDimitry Andric } 18340b57cec5SDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 18350b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 18360b57cec5SDimitry Andric TII->insertBranch(*IfBB, MergeBB, CodeBBStart, Cond, DL); 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric return IfBB; 18390b57cec5SDimitry Andric } 18400b57cec5SDimitry Andric 18410b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::ensureCondIsNotKilled( 18420b57cec5SDimitry Andric SmallVector<MachineOperand, 1> Cond) { 18430b57cec5SDimitry Andric if (Cond.size() != 1) 18440b57cec5SDimitry Andric return; 18450b57cec5SDimitry Andric if (!Cond[0].isReg()) 18460b57cec5SDimitry Andric return; 18470b57cec5SDimitry Andric 18488bcb0991SDimitry Andric Register CondReg = Cond[0].getReg(); 1849*349cc55cSDimitry Andric for (MachineOperand &MO : MRI->use_operands(CondReg)) 1850*349cc55cSDimitry Andric MO.setIsKill(false); 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteCodeBBTerminator(MachineBasicBlock *CodeBB, 18540b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 18550b57cec5SDimitry Andric unsigned BBSelectReg) { 18560b57cec5SDimitry Andric MachineBasicBlock *TrueBB = nullptr; 18570b57cec5SDimitry Andric MachineBasicBlock *FalseBB = nullptr; 18580b57cec5SDimitry Andric SmallVector<MachineOperand, 1> Cond; 18590b57cec5SDimitry Andric MachineBasicBlock *FallthroughBB = FallthroughMap[CodeBB]; 18600b57cec5SDimitry Andric TII->analyzeBranch(*CodeBB, TrueBB, FalseBB, Cond); 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric const DebugLoc &DL = CodeBB->findDebugLoc(CodeBB->getFirstTerminator()); 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr && FallthroughBB == nullptr) { 18650b57cec5SDimitry Andric // This is an exit block, hence no successors. We will assign the 18660b57cec5SDimitry Andric // bb select register to the entry block. 18670b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18680b57cec5SDimitry Andric BBSelectReg, 18690b57cec5SDimitry Andric CodeBB->getParent()->begin()->getNumber()); 18700b57cec5SDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL); 18710b57cec5SDimitry Andric return; 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric 18740b57cec5SDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr) { 18750b57cec5SDimitry Andric TrueBB = FallthroughBB; 18760b57cec5SDimitry Andric } else if (TrueBB != nullptr) { 18770b57cec5SDimitry Andric FalseBB = 18780b57cec5SDimitry Andric (FallthroughBB && (FallthroughBB != TrueBB)) ? FallthroughBB : FalseBB; 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric if ((TrueBB != nullptr && FalseBB == nullptr) || (TrueBB == FalseBB)) { 18820b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18830b57cec5SDimitry Andric BBSelectReg, TrueBB->getNumber()); 18840b57cec5SDimitry Andric } else { 18850b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectReg); 18868bcb0991SDimitry Andric Register TrueBBReg = MRI->createVirtualRegister(RegClass); 18878bcb0991SDimitry Andric Register FalseBBReg = MRI->createVirtualRegister(RegClass); 18880b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18890b57cec5SDimitry Andric TrueBBReg, TrueBB->getNumber()); 18900b57cec5SDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL, 18910b57cec5SDimitry Andric FalseBBReg, FalseBB->getNumber()); 18920b57cec5SDimitry Andric ensureCondIsNotKilled(Cond); 18930b57cec5SDimitry Andric TII->insertVectorSelect(*CodeBB, CodeBB->getFirstTerminator(), DL, 18940b57cec5SDimitry Andric BBSelectReg, Cond, TrueBBReg, FalseBBReg); 18950b57cec5SDimitry Andric } 18960b57cec5SDimitry Andric 18970b57cec5SDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL); 18980b57cec5SDimitry Andric } 18990b57cec5SDimitry Andric 19000b57cec5SDimitry Andric MachineInstr *AMDGPUMachineCFGStructurizer::getDefInstr(unsigned Reg) { 19010b57cec5SDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) { 19020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 19030b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 19040b57cec5SDimitry Andric << " has NO defs\n"); 19050b57cec5SDimitry Andric } else if (!MRI->hasOneDef(Reg)) { 19060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Register " 19070b57cec5SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo()) 19080b57cec5SDimitry Andric << " has multiple defs\n"); 19090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS BEGIN:\n"); 19100b57cec5SDimitry Andric for (auto DI = MRI->def_begin(Reg), DE = MRI->def_end(); DI != DE; ++DI) { 19110b57cec5SDimitry Andric LLVM_DEBUG(DI->getParent()->dump()); 19120b57cec5SDimitry Andric } 19130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS END\n"); 19140b57cec5SDimitry Andric } 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions"); 19170b57cec5SDimitry Andric return (*(MRI->def_begin(Reg))).getParent(); 19180b57cec5SDimitry Andric } 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::insertChainedPHI(MachineBasicBlock *IfBB, 19210b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 19220b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 19230b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19240b57cec5SDimitry Andric unsigned DestReg, 19250b57cec5SDimitry Andric unsigned SourceReg) { 19260b57cec5SDimitry Andric // In this function we know we are part of a chain already, so we need 19270b57cec5SDimitry Andric // to add the registers to the existing chain, and rename the register 19280b57cec5SDimitry Andric // inside the region. 19290b57cec5SDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 19300b57cec5SDimitry Andric MachineInstr *DefInstr = getDefInstr(SourceReg); 19310b57cec5SDimitry Andric if (DefInstr->isPHI() && DefInstr->getParent() == CodeBB && IsSingleBB) { 19320b57cec5SDimitry Andric // Handle the case where the def is a PHI-def inside a basic 19330b57cec5SDimitry Andric // block, then we only need to do renaming. Special care needs to 19340b57cec5SDimitry Andric // be taken if the PHI-def is part of an existing chain, or if a 19350b57cec5SDimitry Andric // new one needs to be created. 19360b57cec5SDimitry Andric InnerRegion->replaceRegisterInsideRegion(SourceReg, DestReg, true, MRI); 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric // We collect all PHI Information, and if we are at the region entry, 19390b57cec5SDimitry Andric // all PHIs will be removed, and then re-introduced if needed. 19400b57cec5SDimitry Andric storePHILinearizationInfoDest(DestReg, *DefInstr); 19410b57cec5SDimitry Andric // We have picked up all the information we need now and can remove 19420b57cec5SDimitry Andric // the PHI 19430b57cec5SDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 19440b57cec5SDimitry Andric DefInstr->eraseFromParent(); 19450b57cec5SDimitry Andric } else { 19460b57cec5SDimitry Andric // If this is not a phi-def, or it is a phi-def but from a linearized region 19470b57cec5SDimitry Andric if (IsSingleBB && DefInstr->getParent() == InnerRegion->getEntry()) { 19480b57cec5SDimitry Andric // If this is a single BB and the definition is in this block we 19490b57cec5SDimitry Andric // need to replace any uses outside the region. 19500b57cec5SDimitry Andric InnerRegion->replaceRegisterOutsideRegion(SourceReg, DestReg, false, MRI); 19510b57cec5SDimitry Andric } 19520b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(DestReg); 19538bcb0991SDimitry Andric Register NextDestReg = MRI->createVirtualRegister(RegClass); 19540b57cec5SDimitry Andric bool IsLastDef = PHIInfo.getNumSources(DestReg) == 1; 19550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Chained PHI\n"); 19560b57cec5SDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, DestReg, NextDestReg, 19570b57cec5SDimitry Andric SourceReg, IsLastDef); 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB); 19600b57cec5SDimitry Andric if (IsLastDef) { 19610b57cec5SDimitry Andric const DebugLoc &DL = IfBB->findDebugLoc(IfBB->getFirstTerminator()); 19620b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DL, 19630b57cec5SDimitry Andric NextDestReg, 0); 19640b57cec5SDimitry Andric PHIInfo.deleteDef(DestReg); 19650b57cec5SDimitry Andric } else { 19660b57cec5SDimitry Andric PHIInfo.replaceDef(DestReg, NextDestReg); 19670b57cec5SDimitry Andric } 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric 19710b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::containsDef(MachineBasicBlock *MBB, 19720b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19730b57cec5SDimitry Andric unsigned Register) { 19740b57cec5SDimitry Andric return getDefInstr(Register)->getParent() == MBB || 19750b57cec5SDimitry Andric InnerRegion->contains(getDefInstr(Register)->getParent()); 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteLiveOutRegs(MachineBasicBlock *IfBB, 19790b57cec5SDimitry Andric MachineBasicBlock *CodeBB, 19800b57cec5SDimitry Andric MachineBasicBlock *MergeBB, 19810b57cec5SDimitry Andric LinearizedRegion *InnerRegion, 19820b57cec5SDimitry Andric LinearizedRegion *LRegion) { 19830b57cec5SDimitry Andric DenseSet<unsigned> *LiveOuts = InnerRegion->getLiveOuts(); 19840b57cec5SDimitry Andric SmallVector<unsigned, 4> OldLiveOuts; 19850b57cec5SDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit(); 19860b57cec5SDimitry Andric for (auto OLI : *LiveOuts) { 19870b57cec5SDimitry Andric OldLiveOuts.push_back(OLI); 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric for (auto LI : OldLiveOuts) { 19910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "LiveOut: " << printReg(LI, TRI)); 19920b57cec5SDimitry Andric if (!containsDef(CodeBB, InnerRegion, LI) || 19930b57cec5SDimitry Andric (!IsSingleBB && (getDefInstr(LI)->getParent() == LRegion->getExit()))) { 1994*349cc55cSDimitry Andric // If the register simply lives through the CodeBB, we don't have 19950b57cec5SDimitry Andric // to rewrite anything since the register is not defined in this 19960b57cec5SDimitry Andric // part of the code. 19970b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "- through"); 19980b57cec5SDimitry Andric continue; 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 20010b57cec5SDimitry Andric unsigned Reg = LI; 20020b57cec5SDimitry Andric if (/*!PHIInfo.isSource(Reg) &&*/ Reg != InnerRegion->getBBSelectRegOut()) { 20030b57cec5SDimitry Andric // If the register is live out, we do want to create a phi, 2004*349cc55cSDimitry Andric // unless it is from the Exit block, because in that case there 20050b57cec5SDimitry Andric // is already a PHI, and no need to create a new one. 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric // If the register is just a live out def and not part of a phi 20080b57cec5SDimitry Andric // chain, we need to create a PHI node to handle the if region, 20090b57cec5SDimitry Andric // and replace all uses outside of the region with the new dest 20100b57cec5SDimitry Andric // register, unless it is the outgoing BB select register. We have 2011*349cc55cSDimitry Andric // already created phi nodes for these. 20120b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(Reg); 20138bcb0991SDimitry Andric Register PHIDestReg = MRI->createVirtualRegister(RegClass); 20148bcb0991SDimitry Andric Register IfSourceReg = MRI->createVirtualRegister(RegClass); 20150b57cec5SDimitry Andric // Create initializer, this value is never used, but is needed 20160b57cec5SDimitry Andric // to satisfy SSA. 20170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Initializer for reg: " << printReg(Reg) << "\n"); 20180b57cec5SDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DebugLoc(), 20190b57cec5SDimitry Andric IfSourceReg, 0); 20200b57cec5SDimitry Andric 20210b57cec5SDimitry Andric InnerRegion->replaceRegisterOutsideRegion(Reg, PHIDestReg, true, MRI); 20220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Non-Chained Live out PHI\n"); 20230b57cec5SDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, PHIDestReg, 20240b57cec5SDimitry Andric IfSourceReg, Reg, true); 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric // Handle the chained definitions in PHIInfo, checking if this basic block 20290b57cec5SDimitry Andric // is a source block for a definition. 20300b57cec5SDimitry Andric SmallVector<unsigned, 4> Sources; 20310b57cec5SDimitry Andric if (PHIInfo.findSourcesFromMBB(CodeBB, Sources)) { 20320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting PHI Live Out from " 20330b57cec5SDimitry Andric << printMBBReference(*CodeBB) << "\n"); 20340b57cec5SDimitry Andric for (auto SI : Sources) { 20350b57cec5SDimitry Andric unsigned DestReg; 20360b57cec5SDimitry Andric PHIInfo.findDest(SI, CodeBB, DestReg); 20370b57cec5SDimitry Andric insertChainedPHI(IfBB, CodeBB, MergeBB, InnerRegion, DestReg, SI); 20380b57cec5SDimitry Andric } 20390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insertion done.\n"); 20400b57cec5SDimitry Andric } 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20430b57cec5SDimitry Andric } 20440b57cec5SDimitry Andric 20450b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::prunePHIInfo(MachineBasicBlock *MBB) { 20460b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Before PHI Prune\n"); 20470b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20480b57cec5SDimitry Andric SmallVector<std::tuple<unsigned, unsigned, MachineBasicBlock *>, 4> 20490b57cec5SDimitry Andric ElimiatedSources; 20500b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 20510b57cec5SDimitry Andric ++DRI) { 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric unsigned DestReg = *DRI; 20540b57cec5SDimitry Andric auto SE = PHIInfo.sources_end(DestReg); 20550b57cec5SDimitry Andric 20560b57cec5SDimitry Andric bool MBBContainsPHISource = false; 20570b57cec5SDimitry Andric // Check if there is a PHI source in this MBB 20580b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 20590b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 20600b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 20610b57cec5SDimitry Andric if (Def->getParent()->getParent() == MBB) { 20620b57cec5SDimitry Andric MBBContainsPHISource = true; 20630b57cec5SDimitry Andric } 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric // If so, all other sources are useless since we know this block 20670b57cec5SDimitry Andric // is always executed when the region is executed. 20680b57cec5SDimitry Andric if (MBBContainsPHISource) { 20690b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 20700b57cec5SDimitry Andric PHILinearize::PHISourceT Source = *SRI; 20710b57cec5SDimitry Andric unsigned SourceReg = Source.first; 20720b57cec5SDimitry Andric MachineBasicBlock *SourceMBB = Source.second; 20730b57cec5SDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg))); 20740b57cec5SDimitry Andric if (Def->getParent()->getParent() != MBB) { 20750b57cec5SDimitry Andric ElimiatedSources.push_back( 20760b57cec5SDimitry Andric std::make_tuple(DestReg, SourceReg, SourceMBB)); 20770b57cec5SDimitry Andric } 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric } 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric // Remove the PHI sources that are in the given MBB 20830b57cec5SDimitry Andric for (auto &SourceInfo : ElimiatedSources) { 20840b57cec5SDimitry Andric PHIInfo.removeSource(std::get<0>(SourceInfo), std::get<1>(SourceInfo), 20850b57cec5SDimitry Andric std::get<2>(SourceInfo)); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "After PHI Prune\n"); 20880b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 20890b57cec5SDimitry Andric } 20900b57cec5SDimitry Andric 20910b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegion, 20920b57cec5SDimitry Andric unsigned DestReg) { 20930b57cec5SDimitry Andric MachineBasicBlock *Entry = CurrentRegion->getEntry(); 20940b57cec5SDimitry Andric MachineBasicBlock *Exit = CurrentRegion->getExit(); 20950b57cec5SDimitry Andric 20960b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExit: " << Exit->getNumber() << " Pred: " 20970b57cec5SDimitry Andric << (*(Entry->pred_begin()))->getNumber() << "\n"); 20980b57cec5SDimitry Andric 20990b57cec5SDimitry Andric int NumSources = 0; 21000b57cec5SDimitry Andric auto SE = PHIInfo.sources_end(DestReg); 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 21030b57cec5SDimitry Andric NumSources++; 21040b57cec5SDimitry Andric } 21050b57cec5SDimitry Andric 21060b57cec5SDimitry Andric if (NumSources == 1) { 21070b57cec5SDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg); 21080b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 21090b57cec5SDimitry Andric replaceRegisterWith(DestReg, SourceReg); 21100b57cec5SDimitry Andric } else { 21110b57cec5SDimitry Andric const DebugLoc &DL = Entry->findDebugLoc(Entry->begin()); 21120b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*Entry, Entry->instr_begin(), DL, 21130b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), DestReg); 21140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Entry PHI " << printReg(DestReg, TRI) << " = PHI("); 21150b57cec5SDimitry Andric 21160b57cec5SDimitry Andric unsigned CurrentBackedgeReg = 0; 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) { 21190b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric if (CurrentRegion->contains((*SRI).second)) { 21220b57cec5SDimitry Andric if (CurrentBackedgeReg == 0) { 21230b57cec5SDimitry Andric CurrentBackedgeReg = SourceReg; 21240b57cec5SDimitry Andric } else { 21250b57cec5SDimitry Andric MachineInstr *PHIDefInstr = getDefInstr(SourceReg); 21260b57cec5SDimitry Andric MachineBasicBlock *PHIDefMBB = PHIDefInstr->getParent(); 21270b57cec5SDimitry Andric const TargetRegisterClass *RegClass = 21280b57cec5SDimitry Andric MRI->getRegClass(CurrentBackedgeReg); 21298bcb0991SDimitry Andric Register NewBackedgeReg = MRI->createVirtualRegister(RegClass); 21300b57cec5SDimitry Andric MachineInstrBuilder BackedgePHI = 21310b57cec5SDimitry Andric BuildMI(*PHIDefMBB, PHIDefMBB->instr_begin(), DL, 21320b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), NewBackedgeReg); 21330b57cec5SDimitry Andric BackedgePHI.addReg(CurrentBackedgeReg); 21340b57cec5SDimitry Andric BackedgePHI.addMBB(getPHIPred(*PHIDefInstr, 0)); 21350b57cec5SDimitry Andric BackedgePHI.addReg(getPHISourceReg(*PHIDefInstr, 1)); 21360b57cec5SDimitry Andric BackedgePHI.addMBB((*SRI).second); 21370b57cec5SDimitry Andric CurrentBackedgeReg = NewBackedgeReg; 21380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 21390b57cec5SDimitry Andric << "Inserting backedge PHI: " 21400b57cec5SDimitry Andric << printReg(NewBackedgeReg, TRI) << " = PHI(" 21410b57cec5SDimitry Andric << printReg(CurrentBackedgeReg, TRI) << ", " 21420b57cec5SDimitry Andric << printMBBReference(*getPHIPred(*PHIDefInstr, 0)) << ", " 21430b57cec5SDimitry Andric << printReg(getPHISourceReg(*PHIDefInstr, 1), TRI) << ", " 21440b57cec5SDimitry Andric << printMBBReference(*(*SRI).second)); 21450b57cec5SDimitry Andric } 21460b57cec5SDimitry Andric } else { 21470b57cec5SDimitry Andric MIB.addReg(SourceReg); 21480b57cec5SDimitry Andric MIB.addMBB((*SRI).second); 21490b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", " 21500b57cec5SDimitry Andric << printMBBReference(*(*SRI).second) << ", "); 21510b57cec5SDimitry Andric } 21520b57cec5SDimitry Andric } 21530b57cec5SDimitry Andric 21540b57cec5SDimitry Andric // Add the final backedge register source to the entry phi 21550b57cec5SDimitry Andric if (CurrentBackedgeReg != 0) { 21560b57cec5SDimitry Andric MIB.addReg(CurrentBackedgeReg); 21570b57cec5SDimitry Andric MIB.addMBB(Exit); 21580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CurrentBackedgeReg, TRI) << ", " 21590b57cec5SDimitry Andric << printMBBReference(*Exit) << ")\n"); 21600b57cec5SDimitry Andric } else { 21610b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ")\n"); 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric } 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric 21660b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHIs(LinearizedRegion *CurrentRegion) { 21670b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 21680b57cec5SDimitry Andric 21690b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 21700b57cec5SDimitry Andric ++DRI) { 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric unsigned DestReg = *DRI; 21730b57cec5SDimitry Andric createEntryPHI(CurrentRegion, DestReg); 21740b57cec5SDimitry Andric } 21750b57cec5SDimitry Andric PHIInfo.clear(); 21760b57cec5SDimitry Andric } 21770b57cec5SDimitry Andric 2178e8d8bef9SDimitry Andric void AMDGPUMachineCFGStructurizer::replaceRegisterWith( 2179e8d8bef9SDimitry Andric unsigned Register, class Register NewRegister) { 21800b57cec5SDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself"); 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register), 21830b57cec5SDimitry Andric E = MRI->reg_end(); 21840b57cec5SDimitry Andric I != E;) { 21850b57cec5SDimitry Andric MachineOperand &O = *I; 21860b57cec5SDimitry Andric ++I; 2187e8d8bef9SDimitry Andric if (NewRegister.isPhysical()) { 21880b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: " 21890b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 21900b57cec5SDimitry Andric << "\n"); 21910b57cec5SDimitry Andric llvm_unreachable("Cannot substitute physical registers"); 21920b57cec5SDimitry Andric // We don't handle physical registers, but if we need to 21930b57cec5SDimitry Andric // in the future This is how we do it: 21940b57cec5SDimitry Andric // O.substPhysReg(NewRegister, *TRI); 21950b57cec5SDimitry Andric } else { 21960b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register: " 21970b57cec5SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) 21980b57cec5SDimitry Andric << " with " 21990b57cec5SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) 22000b57cec5SDimitry Andric << "\n"); 22010b57cec5SDimitry Andric O.setReg(NewRegister); 22020b57cec5SDimitry Andric } 22030b57cec5SDimitry Andric } 22040b57cec5SDimitry Andric PHIInfo.deleteDef(Register); 22050b57cec5SDimitry Andric 22060b57cec5SDimitry Andric getRegionMRT()->replaceLiveOutReg(Register, NewRegister); 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 22090b57cec5SDimitry Andric } 22100b57cec5SDimitry Andric 22110b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::resolvePHIInfos(MachineBasicBlock *FunctionEntry) { 22120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Resolve PHI Infos\n"); 22130b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 22140b57cec5SDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE; 22150b57cec5SDimitry Andric ++DRI) { 22160b57cec5SDimitry Andric unsigned DestReg = *DRI; 22170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI) << "\n"); 22180b57cec5SDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg); 22190b57cec5SDimitry Andric unsigned SourceReg = (*SRI).first; 22200b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI) 22210b57cec5SDimitry Andric << " SourceReg: " << printReg(SourceReg, TRI) << "\n"); 22220b57cec5SDimitry Andric 22230b57cec5SDimitry Andric assert(PHIInfo.sources_end(DestReg) == ++SRI && 22240b57cec5SDimitry Andric "More than one phi source in entry node"); 22250b57cec5SDimitry Andric replaceRegisterWith(DestReg, SourceReg); 22260b57cec5SDimitry Andric } 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric static bool isFunctionEntryBlock(MachineBasicBlock *MBB) { 22300b57cec5SDimitry Andric return ((&(*(MBB->getParent()->begin()))) == MBB); 22310b57cec5SDimitry Andric } 22320b57cec5SDimitry Andric 22330b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 22340b57cec5SDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBB, 22350b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, unsigned BBSelectRegIn, 22360b57cec5SDimitry Andric unsigned BBSelectRegOut) { 22370b57cec5SDimitry Andric if (isFunctionEntryBlock(CodeBB) && !CurrentRegion->getHasLoop()) { 22380b57cec5SDimitry Andric // Handle non-loop function entry block. 22390b57cec5SDimitry Andric // We need to allow loops to the entry block and then 22400b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 22410b57cec5SDimitry Andric resolvePHIInfos(CodeBB); 22420b57cec5SDimitry Andric removeExternalCFGSuccessors(CodeBB); 22430b57cec5SDimitry Andric CodeBB->addSuccessor(MergeBB); 22440b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 22450b57cec5SDimitry Andric return nullptr; 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric if (CurrentRegion->getEntry() == CodeBB && !CurrentRegion->getHasLoop()) { 22480b57cec5SDimitry Andric // Handle non-loop region entry block. 22490b57cec5SDimitry Andric MachineFunction *MF = MergeBB->getParent(); 22500b57cec5SDimitry Andric auto MergeIter = MergeBB->getIterator(); 22510b57cec5SDimitry Andric auto CodeBBStartIter = CodeBB->getIterator(); 22520b57cec5SDimitry Andric auto CodeBBEndIter = ++(CodeBB->getIterator()); 22530b57cec5SDimitry Andric if (CodeBBEndIter != MergeIter) { 22540b57cec5SDimitry Andric MF->splice(MergeIter, CodeBBStartIter, CodeBBEndIter); 22550b57cec5SDimitry Andric } 22560b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut); 22570b57cec5SDimitry Andric prunePHIInfo(CodeBB); 22580b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 22590b57cec5SDimitry Andric removeExternalCFGSuccessors(CodeBB); 22600b57cec5SDimitry Andric CodeBB->addSuccessor(MergeBB); 22610b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 22620b57cec5SDimitry Andric return nullptr; 22630b57cec5SDimitry Andric } else { 22640b57cec5SDimitry Andric // Handle internal block. 22650b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectRegIn); 22668bcb0991SDimitry Andric Register CodeBBSelectReg = MRI->createVirtualRegister(RegClass); 22670b57cec5SDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, CodeBBSelectReg); 22680b57cec5SDimitry Andric bool IsRegionEntryBB = CurrentRegion->getEntry() == CodeBB; 22690b57cec5SDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeBB, CodeBB, CodeBB, 22700b57cec5SDimitry Andric BBSelectRegIn, IsRegionEntryBB); 22710b57cec5SDimitry Andric CurrentRegion->addMBB(IfBB); 22720b57cec5SDimitry Andric // If this is the entry block we need to make the If block the new 22730b57cec5SDimitry Andric // linearized region entry. 22740b57cec5SDimitry Andric if (IsRegionEntryBB) { 22750b57cec5SDimitry Andric CurrentRegion->setEntry(IfBB); 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric if (CurrentRegion->getHasLoop()) { 22780b57cec5SDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 22790b57cec5SDimitry Andric MachineBasicBlock *ETrueBB = nullptr; 22800b57cec5SDimitry Andric MachineBasicBlock *EFalseBB = nullptr; 22810b57cec5SDimitry Andric SmallVector<MachineOperand, 1> ECond; 22820b57cec5SDimitry Andric 22830b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc(); 22840b57cec5SDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 22850b57cec5SDimitry Andric TII->removeBranch(*RegionExit); 22860b57cec5SDimitry Andric 22870b57cec5SDimitry Andric // We need to create a backedge if there is a loop 2288e8d8bef9SDimitry Andric Register Reg = TII->insertNE( 22890b57cec5SDimitry Andric RegionExit, RegionExit->instr_end(), DL, 22900b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 22910b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 22920b57cec5SDimitry Andric MachineOperand RegOp = 22930b57cec5SDimitry Andric MachineOperand::CreateReg(Reg, false, false, true); 22940b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 22950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: "); 22960b57cec5SDimitry Andric LLVM_DEBUG(Cond[0].print(dbgs(), TRI)); 22970b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 22980b57cec5SDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 22990b57cec5SDimitry Andric Cond, DebugLoc()); 23000b57cec5SDimitry Andric RegionExit->addSuccessor(CurrentRegion->getEntry()); 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric } 23030b57cec5SDimitry Andric CurrentRegion->addMBB(CodeBB); 23040b57cec5SDimitry Andric LinearizedRegion InnerRegion(CodeBB, MRI, TRI, PHIInfo); 23050b57cec5SDimitry Andric 23060b57cec5SDimitry Andric InnerRegion.setParent(CurrentRegion); 23070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (BB)\n"); 23080b57cec5SDimitry Andric insertMergePHI(IfBB, CodeBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 23090b57cec5SDimitry Andric CodeBBSelectReg); 23100b57cec5SDimitry Andric InnerRegion.addMBB(MergeBB); 23110b57cec5SDimitry Andric 23120b57cec5SDimitry Andric LLVM_DEBUG(InnerRegion.print(dbgs(), TRI)); 23130b57cec5SDimitry Andric rewriteLiveOutRegs(IfBB, CodeBB, MergeBB, &InnerRegion, CurrentRegion); 23140b57cec5SDimitry Andric extractKilledPHIs(CodeBB); 23150b57cec5SDimitry Andric if (IsRegionEntryBB) { 23160b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 23170b57cec5SDimitry Andric } 23180b57cec5SDimitry Andric return IfBB; 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion( 23230b57cec5SDimitry Andric MachineBasicBlock *MergeBB, LinearizedRegion *InnerRegion, 23240b57cec5SDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB, 23250b57cec5SDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut) { 23260b57cec5SDimitry Andric unsigned CodeBBSelectReg = 23270b57cec5SDimitry Andric InnerRegion->getRegionMRT()->getInnerOutputRegister(); 23280b57cec5SDimitry Andric MachineBasicBlock *CodeEntryBB = InnerRegion->getEntry(); 23290b57cec5SDimitry Andric MachineBasicBlock *CodeExitBB = InnerRegion->getExit(); 23300b57cec5SDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeEntryBB, CodeExitBB, 23310b57cec5SDimitry Andric SelectBB, BBSelectRegIn, true); 23320b57cec5SDimitry Andric CurrentRegion->addMBB(IfBB); 23330b57cec5SDimitry Andric bool isEntry = CurrentRegion->getEntry() == InnerRegion->getEntry(); 23340b57cec5SDimitry Andric if (isEntry) { 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric if (CurrentRegion->getHasLoop()) { 23370b57cec5SDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit(); 23380b57cec5SDimitry Andric MachineBasicBlock *ETrueBB = nullptr; 23390b57cec5SDimitry Andric MachineBasicBlock *EFalseBB = nullptr; 23400b57cec5SDimitry Andric SmallVector<MachineOperand, 1> ECond; 23410b57cec5SDimitry Andric 23420b57cec5SDimitry Andric const DebugLoc &DL = DebugLoc(); 23430b57cec5SDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond); 23440b57cec5SDimitry Andric TII->removeBranch(*RegionExit); 23450b57cec5SDimitry Andric 23460b57cec5SDimitry Andric // We need to create a backedge if there is a loop 2347e8d8bef9SDimitry Andric Register Reg = 23480b57cec5SDimitry Andric TII->insertNE(RegionExit, RegionExit->instr_end(), DL, 23490b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(), 23500b57cec5SDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber()); 23510b57cec5SDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true); 23520b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond(RegOp); 23530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: "); 23540b57cec5SDimitry Andric LLVM_DEBUG(Cond[0].print(dbgs(), TRI)); 23550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 23560b57cec5SDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit, 23570b57cec5SDimitry Andric Cond, DebugLoc()); 23580b57cec5SDimitry Andric RegionExit->addSuccessor(IfBB); 23590b57cec5SDimitry Andric } 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric CurrentRegion->addMBBs(InnerRegion); 23620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (region)\n"); 23630b57cec5SDimitry Andric insertMergePHI(IfBB, CodeExitBB, MergeBB, BBSelectRegOut, BBSelectRegIn, 23640b57cec5SDimitry Andric CodeBBSelectReg); 23650b57cec5SDimitry Andric 23660b57cec5SDimitry Andric rewriteLiveOutRegs(IfBB, /* CodeEntryBB */ CodeExitBB, MergeBB, InnerRegion, 23670b57cec5SDimitry Andric CurrentRegion); 23680b57cec5SDimitry Andric 23690b57cec5SDimitry Andric rewriteRegionEntryPHIs(InnerRegion, IfBB); 23700b57cec5SDimitry Andric 23710b57cec5SDimitry Andric if (isEntry) { 23720b57cec5SDimitry Andric CurrentRegion->setEntry(IfBB); 23730b57cec5SDimitry Andric } 23740b57cec5SDimitry Andric 23750b57cec5SDimitry Andric if (isEntry) { 23760b57cec5SDimitry Andric createEntryPHIs(CurrentRegion); 23770b57cec5SDimitry Andric } 23780b57cec5SDimitry Andric 23790b57cec5SDimitry Andric return IfBB; 23800b57cec5SDimitry Andric } 23810b57cec5SDimitry Andric 23820b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHI(MachineInstr &PHI, 23830b57cec5SDimitry Andric MachineBasicBlock *Entry, 23840b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, 23850b57cec5SDimitry Andric LinearizedRegion *LRegion) { 23860b57cec5SDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices; 23870b57cec5SDimitry Andric getPHIRegionIndices(LRegion, PHI, PHIRegionIndices); 23880b57cec5SDimitry Andric 23890b57cec5SDimitry Andric assert(PHIRegionIndices.size() == 1); 23900b57cec5SDimitry Andric 23910b57cec5SDimitry Andric unsigned RegionIndex = PHIRegionIndices[0]; 23920b57cec5SDimitry Andric unsigned RegionSourceReg = getPHISourceReg(PHI, RegionIndex); 23930b57cec5SDimitry Andric MachineBasicBlock *RegionSourceMBB = getPHIPred(PHI, RegionIndex); 23940b57cec5SDimitry Andric unsigned PHIDest = getPHIDestReg(PHI); 23950b57cec5SDimitry Andric unsigned PHISource = PHIDest; 23960b57cec5SDimitry Andric unsigned ReplaceReg; 23970b57cec5SDimitry Andric 23980b57cec5SDimitry Andric if (shrinkPHI(PHI, PHIRegionIndices, &ReplaceReg)) { 23990b57cec5SDimitry Andric PHISource = ReplaceReg; 24000b57cec5SDimitry Andric } 24010b57cec5SDimitry Andric 24020b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(PHIDest); 24038bcb0991SDimitry Andric Register NewDestReg = MRI->createVirtualRegister(RegClass); 24040b57cec5SDimitry Andric LRegion->replaceRegisterInsideRegion(PHIDest, NewDestReg, false, MRI); 24050b57cec5SDimitry Andric MachineInstrBuilder MIB = 24060b57cec5SDimitry Andric BuildMI(*EntrySucc, EntrySucc->instr_begin(), PHI.getDebugLoc(), 24070b57cec5SDimitry Andric TII->get(TargetOpcode::PHI), NewDestReg); 24080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split Entry PHI " << printReg(NewDestReg, TRI) 24090b57cec5SDimitry Andric << " = PHI("); 24100b57cec5SDimitry Andric MIB.addReg(PHISource); 24110b57cec5SDimitry Andric MIB.addMBB(Entry); 24120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(PHISource, TRI) << ", " 24130b57cec5SDimitry Andric << printMBBReference(*Entry)); 24140b57cec5SDimitry Andric MIB.addReg(RegionSourceReg); 24150b57cec5SDimitry Andric MIB.addMBB(RegionSourceMBB); 24160b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " ," << printReg(RegionSourceReg, TRI) << ", " 24170b57cec5SDimitry Andric << printMBBReference(*RegionSourceMBB) << ")\n"); 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric 24200b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHIs(MachineBasicBlock *Entry, 24210b57cec5SDimitry Andric MachineBasicBlock *EntrySucc, 24220b57cec5SDimitry Andric LinearizedRegion *LRegion) { 24230b57cec5SDimitry Andric SmallVector<MachineInstr *, 2> PHIs; 24240b57cec5SDimitry Andric collectPHIs(Entry, PHIs); 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric for (auto PHII : PHIs) { 24270b57cec5SDimitry Andric splitLoopPHI(*PHII, Entry, EntrySucc, LRegion); 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric } 24300b57cec5SDimitry Andric 24310b57cec5SDimitry Andric // Split the exit block so that we can insert a end control flow 24320b57cec5SDimitry Andric MachineBasicBlock * 24330b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::splitExit(LinearizedRegion *LRegion) { 24340b57cec5SDimitry Andric auto MRTRegion = LRegion->getRegionMRT(); 24350b57cec5SDimitry Andric auto Exit = LRegion->getExit(); 24360b57cec5SDimitry Andric auto MF = Exit->getParent(); 24370b57cec5SDimitry Andric auto Succ = MRTRegion->getSucc(); 24380b57cec5SDimitry Andric 24390b57cec5SDimitry Andric auto NewExit = MF->CreateMachineBasicBlock(); 24400b57cec5SDimitry Andric auto AfterExitIter = Exit->getIterator(); 24410b57cec5SDimitry Andric AfterExitIter++; 24420b57cec5SDimitry Andric MF->insert(AfterExitIter, NewExit); 24430b57cec5SDimitry Andric Exit->removeSuccessor(Succ); 24440b57cec5SDimitry Andric Exit->addSuccessor(NewExit); 24450b57cec5SDimitry Andric NewExit->addSuccessor(Succ); 24460b57cec5SDimitry Andric insertUnconditionalBranch(NewExit, Succ); 24470b57cec5SDimitry Andric LRegion->addMBB(NewExit); 24480b57cec5SDimitry Andric LRegion->setExit(NewExit); 24490b57cec5SDimitry Andric 24500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Created new exit block: " << NewExit->getNumber() 24510b57cec5SDimitry Andric << "\n"); 24520b57cec5SDimitry Andric 24530b57cec5SDimitry Andric // Replace any PHI Predecessors in the successor with NewExit 24540b57cec5SDimitry Andric for (auto &II : *Succ) { 24550b57cec5SDimitry Andric MachineInstr &Instr = II; 24560b57cec5SDimitry Andric 24570b57cec5SDimitry Andric // If we are past the PHI instructions we are done 24580b57cec5SDimitry Andric if (!Instr.isPHI()) 24590b57cec5SDimitry Andric break; 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric int numPreds = getPHINumInputs(Instr); 24620b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 24630b57cec5SDimitry Andric auto Pred = getPHIPred(Instr, i); 24640b57cec5SDimitry Andric if (Pred == Exit) { 24650b57cec5SDimitry Andric setPhiPred(Instr, i, NewExit); 24660b57cec5SDimitry Andric } 24670b57cec5SDimitry Andric } 24680b57cec5SDimitry Andric } 24690b57cec5SDimitry Andric 24700b57cec5SDimitry Andric return NewExit; 24710b57cec5SDimitry Andric } 24720b57cec5SDimitry Andric 24730b57cec5SDimitry Andric static MachineBasicBlock *split(MachineBasicBlock::iterator I) { 24740b57cec5SDimitry Andric // Create the fall-through block. 24750b57cec5SDimitry Andric MachineBasicBlock *MBB = (*I).getParent(); 24760b57cec5SDimitry Andric MachineFunction *MF = MBB->getParent(); 24770b57cec5SDimitry Andric MachineBasicBlock *SuccMBB = MF->CreateMachineBasicBlock(); 24780b57cec5SDimitry Andric auto MBBIter = ++(MBB->getIterator()); 24790b57cec5SDimitry Andric MF->insert(MBBIter, SuccMBB); 24800b57cec5SDimitry Andric SuccMBB->transferSuccessorsAndUpdatePHIs(MBB); 24810b57cec5SDimitry Andric MBB->addSuccessor(SuccMBB); 24820b57cec5SDimitry Andric 24830b57cec5SDimitry Andric // Splice the code over. 24840b57cec5SDimitry Andric SuccMBB->splice(SuccMBB->end(), MBB, I, MBB->end()); 24850b57cec5SDimitry Andric 24860b57cec5SDimitry Andric return SuccMBB; 24870b57cec5SDimitry Andric } 24880b57cec5SDimitry Andric 24890b57cec5SDimitry Andric // Split the entry block separating PHI-nodes and the rest of the code 24900b57cec5SDimitry Andric // This is needed to insert an initializer for the bb select register 24910b57cec5SDimitry Andric // inloop regions. 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric MachineBasicBlock * 24940b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::splitEntry(LinearizedRegion *LRegion) { 24950b57cec5SDimitry Andric MachineBasicBlock *Entry = LRegion->getEntry(); 24960b57cec5SDimitry Andric MachineBasicBlock *EntrySucc = split(Entry->getFirstNonPHI()); 24970b57cec5SDimitry Andric MachineBasicBlock *Exit = LRegion->getExit(); 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split " << printMBBReference(*Entry) << " to " 25000b57cec5SDimitry Andric << printMBBReference(*Entry) << " -> " 25010b57cec5SDimitry Andric << printMBBReference(*EntrySucc) << "\n"); 25020b57cec5SDimitry Andric LRegion->addMBB(EntrySucc); 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // Make the backedge go to Entry Succ 25050b57cec5SDimitry Andric if (Exit->isSuccessor(Entry)) { 25060b57cec5SDimitry Andric Exit->removeSuccessor(Entry); 25070b57cec5SDimitry Andric } 25080b57cec5SDimitry Andric Exit->addSuccessor(EntrySucc); 25090b57cec5SDimitry Andric MachineInstr &Branch = *(Exit->instr_rbegin()); 25100b57cec5SDimitry Andric for (auto &UI : Branch.uses()) { 25110b57cec5SDimitry Andric if (UI.isMBB() && UI.getMBB() == Entry) { 25120b57cec5SDimitry Andric UI.setMBB(EntrySucc); 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric } 25150b57cec5SDimitry Andric 25160b57cec5SDimitry Andric splitLoopPHIs(Entry, EntrySucc, LRegion); 25170b57cec5SDimitry Andric 25180b57cec5SDimitry Andric return EntrySucc; 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric 25210b57cec5SDimitry Andric LinearizedRegion * 25220b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::initLinearizedRegion(RegionMRT *Region) { 25230b57cec5SDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion(); 25240b57cec5SDimitry Andric LRegion->initLiveOut(Region, MRI, TRI, PHIInfo); 25250b57cec5SDimitry Andric LRegion->setEntry(Region->getEntry()); 25260b57cec5SDimitry Andric return LRegion; 25270b57cec5SDimitry Andric } 25280b57cec5SDimitry Andric 25290b57cec5SDimitry Andric static void removeOldExitPreds(RegionMRT *Region) { 25300b57cec5SDimitry Andric MachineBasicBlock *Exit = Region->getSucc(); 25310b57cec5SDimitry Andric if (Exit == nullptr) { 25320b57cec5SDimitry Andric return; 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric for (MachineBasicBlock::pred_iterator PI = Exit->pred_begin(), 25350b57cec5SDimitry Andric E = Exit->pred_end(); 25360b57cec5SDimitry Andric PI != E; ++PI) { 25370b57cec5SDimitry Andric if (Region->contains(*PI)) { 25380b57cec5SDimitry Andric (*PI)->removeSuccessor(Exit); 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric } 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric static bool mbbHasBackEdge(MachineBasicBlock *MBB, 25440b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 2545*349cc55cSDimitry Andric for (MachineBasicBlock *Succ : MBB->successors()) 2546*349cc55cSDimitry Andric if (MBBs.contains(Succ)) 25470b57cec5SDimitry Andric return true; 25480b57cec5SDimitry Andric return false; 25490b57cec5SDimitry Andric } 25500b57cec5SDimitry Andric 25510b57cec5SDimitry Andric static bool containsNewBackedge(MRT *Tree, 25520b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) { 25530b57cec5SDimitry Andric // Need to traverse this in reverse since it is in post order. 25540b57cec5SDimitry Andric if (Tree == nullptr) 25550b57cec5SDimitry Andric return false; 25560b57cec5SDimitry Andric 25570b57cec5SDimitry Andric if (Tree->isMBB()) { 25580b57cec5SDimitry Andric MachineBasicBlock *MBB = Tree->getMBBMRT()->getMBB(); 25590b57cec5SDimitry Andric MBBs.insert(MBB); 25600b57cec5SDimitry Andric if (mbbHasBackEdge(MBB, MBBs)) { 25610b57cec5SDimitry Andric return true; 25620b57cec5SDimitry Andric } 25630b57cec5SDimitry Andric } else { 25640b57cec5SDimitry Andric RegionMRT *Region = Tree->getRegionMRT(); 2565*349cc55cSDimitry Andric for (MRT *C : llvm::reverse(*Region->getChildren())) 2566*349cc55cSDimitry Andric if (containsNewBackedge(C, MBBs)) 25670b57cec5SDimitry Andric return true; 25680b57cec5SDimitry Andric } 25690b57cec5SDimitry Andric return false; 25700b57cec5SDimitry Andric } 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric static bool containsNewBackedge(RegionMRT *Region) { 25730b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> MBBs; 25740b57cec5SDimitry Andric return containsNewBackedge(Region, MBBs); 25750b57cec5SDimitry Andric } 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeComplexRegion(RegionMRT *Region) { 25780b57cec5SDimitry Andric auto *LRegion = initLinearizedRegion(Region); 25790b57cec5SDimitry Andric LRegion->setHasLoop(containsNewBackedge(Region)); 25800b57cec5SDimitry Andric MachineBasicBlock *LastMerge = createLinearizedExitBlock(Region); 25810b57cec5SDimitry Andric MachineBasicBlock *CurrentMerge = LastMerge; 25820b57cec5SDimitry Andric LRegion->addMBB(LastMerge); 25830b57cec5SDimitry Andric LRegion->setExit(LastMerge); 25840b57cec5SDimitry Andric 25850b57cec5SDimitry Andric rewriteRegionExitPHIs(Region, LastMerge, LRegion); 25860b57cec5SDimitry Andric removeOldExitPreds(Region); 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 25890b57cec5SDimitry Andric 25900b57cec5SDimitry Andric SetVector<MRT *> *Children = Region->getChildren(); 25910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region Start===============\n"); 25920b57cec5SDimitry Andric if (LRegion->getHasLoop()) { 25930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: Yes\n"); 25940b57cec5SDimitry Andric } else { 25950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: No\n"); 25960b57cec5SDimitry Andric } 25970b57cec5SDimitry Andric 25980b57cec5SDimitry Andric unsigned BBSelectRegIn; 25990b57cec5SDimitry Andric unsigned BBSelectRegOut; 26000b57cec5SDimitry Andric for (auto CI = Children->begin(), CE = Children->end(); CI != CE; ++CI) { 26010b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CurrentRegion: \n"); 26020b57cec5SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI)); 26030b57cec5SDimitry Andric 26040b57cec5SDimitry Andric auto CNI = CI; 26050b57cec5SDimitry Andric ++CNI; 26060b57cec5SDimitry Andric 26070b57cec5SDimitry Andric MRT *Child = (*CI); 26080b57cec5SDimitry Andric 26090b57cec5SDimitry Andric if (Child->isRegion()) { 26100b57cec5SDimitry Andric 26110b57cec5SDimitry Andric LinearizedRegion *InnerLRegion = 26120b57cec5SDimitry Andric Child->getRegionMRT()->getLinearizedRegion(); 26130b57cec5SDimitry Andric // We found the block is the exit of an inner region, we need 26140b57cec5SDimitry Andric // to put it in the current linearized region. 26150b57cec5SDimitry Andric 26160b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing region: "); 26170b57cec5SDimitry Andric LLVM_DEBUG(InnerLRegion->print(dbgs(), TRI)); 26180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 26190b57cec5SDimitry Andric 26200b57cec5SDimitry Andric MachineBasicBlock *InnerEntry = InnerLRegion->getEntry(); 26210b57cec5SDimitry Andric if ((&(*(InnerEntry->getParent()->begin()))) == InnerEntry) { 26220b57cec5SDimitry Andric // Entry has already been linearized, no need to do this region. 26230b57cec5SDimitry Andric unsigned OuterSelect = InnerLRegion->getBBSelectRegOut(); 26240b57cec5SDimitry Andric unsigned InnerSelectReg = 26250b57cec5SDimitry Andric InnerLRegion->getRegionMRT()->getInnerOutputRegister(); 26260b57cec5SDimitry Andric replaceRegisterWith(InnerSelectReg, OuterSelect), 26270b57cec5SDimitry Andric resolvePHIInfos(InnerEntry); 26280b57cec5SDimitry Andric if (!InnerLRegion->getExit()->isSuccessor(CurrentMerge)) 26290b57cec5SDimitry Andric InnerLRegion->getExit()->addSuccessor(CurrentMerge); 26300b57cec5SDimitry Andric continue; 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut(); 26340b57cec5SDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn(); 26350b57cec5SDimitry Andric 26360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI) 26370b57cec5SDimitry Andric << "\n"); 26380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI) 26390b57cec5SDimitry Andric << "\n"); 26400b57cec5SDimitry Andric 26410b57cec5SDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge; 26420b57cec5SDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, InnerLRegion, LRegion, 26430b57cec5SDimitry Andric Child->getRegionMRT()->getEntry(), 26440b57cec5SDimitry Andric BBSelectRegIn, BBSelectRegOut); 26450b57cec5SDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 26460b57cec5SDimitry Andric } else { 26470b57cec5SDimitry Andric MachineBasicBlock *MBB = Child->getMBBMRT()->getMBB(); 26480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing block: " << MBB->getNumber() << "\n"); 26490b57cec5SDimitry Andric 26500b57cec5SDimitry Andric if (MBB == getSingleExitNode(*(MBB->getParent()))) { 26510b57cec5SDimitry Andric // If this is the exit block then we need to skip to the next. 26520b57cec5SDimitry Andric // The "in" register will be transferred to "out" in the next 26530b57cec5SDimitry Andric // iteration. 26540b57cec5SDimitry Andric continue; 26550b57cec5SDimitry Andric } 26560b57cec5SDimitry Andric 26570b57cec5SDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut(); 26580b57cec5SDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn(); 26590b57cec5SDimitry Andric 26600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI) 26610b57cec5SDimitry Andric << "\n"); 26620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI) 26630b57cec5SDimitry Andric << "\n"); 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge; 26660b57cec5SDimitry Andric // This is a basic block that is not part of an inner region, we 26670b57cec5SDimitry Andric // need to put it in the current linearized region. 26680b57cec5SDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, MBB, LRegion, BBSelectRegIn, 26690b57cec5SDimitry Andric BBSelectRegOut); 26700b57cec5SDimitry Andric if (CurrentMerge) { 26710b57cec5SDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd); 26720b57cec5SDimitry Andric } 26730b57cec5SDimitry Andric 26740b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 26750b57cec5SDimitry Andric } 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric LRegion->removeFalseRegisterKills(MRI); 26790b57cec5SDimitry Andric 26800b57cec5SDimitry Andric if (LRegion->getHasLoop()) { 26810b57cec5SDimitry Andric MachineBasicBlock *NewSucc = splitEntry(LRegion); 26820b57cec5SDimitry Andric if (isFunctionEntryBlock(LRegion->getEntry())) { 26830b57cec5SDimitry Andric resolvePHIInfos(LRegion->getEntry()); 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric const DebugLoc &DL = NewSucc->findDebugLoc(NewSucc->getFirstNonPHI()); 26860b57cec5SDimitry Andric unsigned InReg = LRegion->getBBSelectRegIn(); 26878bcb0991SDimitry Andric Register InnerSelectReg = 26880b57cec5SDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(InReg)); 26898bcb0991SDimitry Andric Register NewInReg = MRI->createVirtualRegister(MRI->getRegClass(InReg)); 26900b57cec5SDimitry Andric TII->materializeImmediate(*(LRegion->getEntry()), 26910b57cec5SDimitry Andric LRegion->getEntry()->getFirstTerminator(), DL, 26920b57cec5SDimitry Andric NewInReg, Region->getEntry()->getNumber()); 26930b57cec5SDimitry Andric // Need to be careful about updating the registers inside the region. 26940b57cec5SDimitry Andric LRegion->replaceRegisterInsideRegion(InReg, InnerSelectReg, false, MRI); 26950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Loop BBSelect Merge PHI:\n"); 26960b57cec5SDimitry Andric insertMergePHI(LRegion->getEntry(), LRegion->getExit(), NewSucc, 26970b57cec5SDimitry Andric InnerSelectReg, NewInReg, 26980b57cec5SDimitry Andric LRegion->getRegionMRT()->getInnerOutputRegister()); 26990b57cec5SDimitry Andric splitExit(LRegion); 27000b57cec5SDimitry Andric TII->convertNonUniformLoopRegion(NewSucc, LastMerge); 27010b57cec5SDimitry Andric } 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric if (Region->isRoot()) { 27040b57cec5SDimitry Andric TII->insertReturn(*LastMerge); 27050b57cec5SDimitry Andric } 27060b57cec5SDimitry Andric 27070b57cec5SDimitry Andric LLVM_DEBUG(Region->getEntry()->getParent()->dump()); 27080b57cec5SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI)); 27090b57cec5SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI)); 27100b57cec5SDimitry Andric 27110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region End===============\n"); 27120b57cec5SDimitry Andric 27130b57cec5SDimitry Andric Region->setLinearizedRegion(LRegion); 27140b57cec5SDimitry Andric return true; 27150b57cec5SDimitry Andric } 27160b57cec5SDimitry Andric 27170b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegion(RegionMRT *Region) { 27180b57cec5SDimitry Andric if (false && regionIsSimpleIf(Region)) { 27190b57cec5SDimitry Andric transformSimpleIfRegion(Region); 27200b57cec5SDimitry Andric return true; 27210b57cec5SDimitry Andric } else if (regionIsSequence(Region)) { 27220b57cec5SDimitry Andric fixupRegionExits(Region); 27230b57cec5SDimitry Andric return false; 27240b57cec5SDimitry Andric } else { 27250b57cec5SDimitry Andric structurizeComplexRegion(Region); 27260b57cec5SDimitry Andric } 27270b57cec5SDimitry Andric return false; 27280b57cec5SDimitry Andric } 27290b57cec5SDimitry Andric 27300b57cec5SDimitry Andric static int structurize_once = 0; 27310b57cec5SDimitry Andric 27320b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegions(RegionMRT *Region, 27330b57cec5SDimitry Andric bool isTopRegion) { 27340b57cec5SDimitry Andric bool Changed = false; 27350b57cec5SDimitry Andric 27360b57cec5SDimitry Andric auto Children = Region->getChildren(); 27370b57cec5SDimitry Andric for (auto CI : *Children) { 27380b57cec5SDimitry Andric if (CI->isRegion()) { 27390b57cec5SDimitry Andric Changed |= structurizeRegions(CI->getRegionMRT(), false); 27400b57cec5SDimitry Andric } 27410b57cec5SDimitry Andric } 27420b57cec5SDimitry Andric 27430b57cec5SDimitry Andric if (structurize_once < 2 || true) { 27440b57cec5SDimitry Andric Changed |= structurizeRegion(Region); 27450b57cec5SDimitry Andric structurize_once++; 27460b57cec5SDimitry Andric } 27470b57cec5SDimitry Andric return Changed; 27480b57cec5SDimitry Andric } 27490b57cec5SDimitry Andric 27500b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::initFallthroughMap(MachineFunction &MF) { 27510b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough Map:\n"); 27520b57cec5SDimitry Andric for (auto &MBBI : MF) { 27530b57cec5SDimitry Andric MachineBasicBlock *MBB = MBBI.getFallThrough(); 27540b57cec5SDimitry Andric if (MBB != nullptr) { 27550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough: " << MBBI.getNumber() << " -> " 27560b57cec5SDimitry Andric << MBB->getNumber() << "\n"); 27570b57cec5SDimitry Andric } 27580b57cec5SDimitry Andric FallthroughMap[&MBBI] = MBB; 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 27620b57cec5SDimitry Andric void AMDGPUMachineCFGStructurizer::createLinearizedRegion(RegionMRT *Region, 27630b57cec5SDimitry Andric unsigned SelectOut) { 27640b57cec5SDimitry Andric LinearizedRegion *LRegion = new LinearizedRegion(); 27650b57cec5SDimitry Andric if (SelectOut) { 27660b57cec5SDimitry Andric LRegion->addLiveOut(SelectOut); 27670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (BBSelect): " << printReg(SelectOut, TRI) 27680b57cec5SDimitry Andric << "\n"); 27690b57cec5SDimitry Andric } 27700b57cec5SDimitry Andric LRegion->setRegionMRT(Region); 27710b57cec5SDimitry Andric Region->setLinearizedRegion(LRegion); 27720b57cec5SDimitry Andric LRegion->setParent(Region->getParent() 27730b57cec5SDimitry Andric ? Region->getParent()->getLinearizedRegion() 27740b57cec5SDimitry Andric : nullptr); 27750b57cec5SDimitry Andric } 27760b57cec5SDimitry Andric 27770b57cec5SDimitry Andric unsigned 27780b57cec5SDimitry Andric AMDGPUMachineCFGStructurizer::initializeSelectRegisters(MRT *MRT, unsigned SelectOut, 27790b57cec5SDimitry Andric MachineRegisterInfo *MRI, 27800b57cec5SDimitry Andric const SIInstrInfo *TII) { 27810b57cec5SDimitry Andric if (MRT->isRegion()) { 27820b57cec5SDimitry Andric RegionMRT *Region = MRT->getRegionMRT(); 27830b57cec5SDimitry Andric Region->setBBSelectRegOut(SelectOut); 27840b57cec5SDimitry Andric unsigned InnerSelectOut = createBBSelectReg(TII, MRI); 27850b57cec5SDimitry Andric 27860b57cec5SDimitry Andric // Fixme: Move linearization creation to the original spot 27870b57cec5SDimitry Andric createLinearizedRegion(Region, SelectOut); 27880b57cec5SDimitry Andric 27890b57cec5SDimitry Andric for (auto CI = Region->getChildren()->begin(), 27900b57cec5SDimitry Andric CE = Region->getChildren()->end(); 27910b57cec5SDimitry Andric CI != CE; ++CI) { 27920b57cec5SDimitry Andric InnerSelectOut = 27930b57cec5SDimitry Andric initializeSelectRegisters((*CI), InnerSelectOut, MRI, TII); 27940b57cec5SDimitry Andric } 27950b57cec5SDimitry Andric MRT->setBBSelectRegIn(InnerSelectOut); 27960b57cec5SDimitry Andric return InnerSelectOut; 27970b57cec5SDimitry Andric } else { 27980b57cec5SDimitry Andric MRT->setBBSelectRegOut(SelectOut); 27990b57cec5SDimitry Andric unsigned NewSelectIn = createBBSelectReg(TII, MRI); 28000b57cec5SDimitry Andric MRT->setBBSelectRegIn(NewSelectIn); 28010b57cec5SDimitry Andric return NewSelectIn; 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric } 28040b57cec5SDimitry Andric 28050b57cec5SDimitry Andric static void checkRegOnlyPHIInputs(MachineFunction &MF) { 28060b57cec5SDimitry Andric for (auto &MBBI : MF) { 28070b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator I = MBBI.instr_begin(), 28080b57cec5SDimitry Andric E = MBBI.instr_end(); 28090b57cec5SDimitry Andric I != E; ++I) { 28100b57cec5SDimitry Andric MachineInstr &Instr = *I; 28110b57cec5SDimitry Andric if (Instr.isPHI()) { 28120b57cec5SDimitry Andric int numPreds = getPHINumInputs(Instr); 28130b57cec5SDimitry Andric for (int i = 0; i < numPreds; ++i) { 28140b57cec5SDimitry Andric assert(Instr.getOperand(i * 2 + 1).isReg() && 28150b57cec5SDimitry Andric "PHI Operand not a register"); 28160b57cec5SDimitry Andric } 28170b57cec5SDimitry Andric } 28180b57cec5SDimitry Andric } 28190b57cec5SDimitry Andric } 28200b57cec5SDimitry Andric } 28210b57cec5SDimitry Andric 28220b57cec5SDimitry Andric bool AMDGPUMachineCFGStructurizer::runOnMachineFunction(MachineFunction &MF) { 28230b57cec5SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 28240b57cec5SDimitry Andric const SIInstrInfo *TII = ST.getInstrInfo(); 28250b57cec5SDimitry Andric TRI = ST.getRegisterInfo(); 28260b57cec5SDimitry Andric MRI = &(MF.getRegInfo()); 28270b57cec5SDimitry Andric initFallthroughMap(MF); 28280b57cec5SDimitry Andric 28290b57cec5SDimitry Andric checkRegOnlyPHIInputs(MF); 28300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER START----\n"); 28310b57cec5SDimitry Andric LLVM_DEBUG(MF.dump()); 28320b57cec5SDimitry Andric 28330b57cec5SDimitry Andric Regions = &(getAnalysis<MachineRegionInfoPass>().getRegionInfo()); 28340b57cec5SDimitry Andric LLVM_DEBUG(Regions->dump()); 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric RegionMRT *RTree = MRT::buildMRT(MF, Regions, TII, MRI); 28370b57cec5SDimitry Andric setRegionMRT(RTree); 28380b57cec5SDimitry Andric initializeSelectRegisters(RTree, 0, MRI, TII); 28390b57cec5SDimitry Andric LLVM_DEBUG(RTree->dump(TRI)); 28400b57cec5SDimitry Andric bool result = structurizeRegions(RTree, true); 28410b57cec5SDimitry Andric delete RTree; 28420b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER END----\n"); 28430b57cec5SDimitry Andric initFallthroughMap(MF); 28440b57cec5SDimitry Andric return result; 28450b57cec5SDimitry Andric } 28460b57cec5SDimitry Andric 28470b57cec5SDimitry Andric char AMDGPUMachineCFGStructurizerID = AMDGPUMachineCFGStructurizer::ID; 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 28500b57cec5SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false) 28510b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineRegionInfoPass) 28520b57cec5SDimitry Andric INITIALIZE_PASS_END(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer", 28530b57cec5SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false) 28540b57cec5SDimitry Andric 28550b57cec5SDimitry Andric FunctionPass *llvm::createAMDGPUMachineCFGStructurizerPass() { 28560b57cec5SDimitry Andric return new AMDGPUMachineCFGStructurizer(); 28570b57cec5SDimitry Andric } 2858