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