16b3f41edSDimitry Andric //===- AMDGPUMachineCFGStructurizer.cpp - Machine code if conversion pass. ===//
26b3f41edSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66b3f41edSDimitry Andric //
76b3f41edSDimitry Andric //===----------------------------------------------------------------------===//
86b3f41edSDimitry Andric //
96b3f41edSDimitry Andric // This file implements the machine instruction level CFG structurizer pass.
106b3f41edSDimitry Andric //
116b3f41edSDimitry Andric //===----------------------------------------------------------------------===//
126b3f41edSDimitry Andric
136b3f41edSDimitry Andric #include "AMDGPU.h"
14b60736ecSDimitry Andric #include "GCNSubtarget.h"
156b3f41edSDimitry Andric #include "llvm/ADT/DenseSet.h"
166b3f41edSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
176b3f41edSDimitry Andric #include "llvm/ADT/SetVector.h"
186b3f41edSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
196b3f41edSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
206b3f41edSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
216b3f41edSDimitry Andric #include "llvm/CodeGen/MachineRegionInfo.h"
226b3f41edSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
23044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
24706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
25044eb2f6SDimitry Andric
266b3f41edSDimitry Andric using namespace llvm;
276b3f41edSDimitry Andric
286b3f41edSDimitry Andric #define DEBUG_TYPE "amdgpucfgstructurizer"
296b3f41edSDimitry Andric
306b3f41edSDimitry Andric namespace {
31044eb2f6SDimitry Andric
326b3f41edSDimitry Andric class PHILinearizeDestIterator;
336b3f41edSDimitry Andric
346b3f41edSDimitry Andric class PHILinearize {
356b3f41edSDimitry Andric friend class PHILinearizeDestIterator;
366b3f41edSDimitry Andric
376b3f41edSDimitry Andric public:
38044eb2f6SDimitry Andric using PHISourceT = std::pair<unsigned, MachineBasicBlock *>;
396b3f41edSDimitry Andric
406b3f41edSDimitry Andric private:
41044eb2f6SDimitry Andric using PHISourcesT = DenseSet<PHISourceT>;
42044eb2f6SDimitry Andric using PHIInfoElementT = struct {
436b3f41edSDimitry Andric unsigned DestReg;
446b3f41edSDimitry Andric DebugLoc DL;
456b3f41edSDimitry Andric PHISourcesT Sources;
46044eb2f6SDimitry Andric };
47044eb2f6SDimitry Andric using PHIInfoT = SmallPtrSet<PHIInfoElementT *, 2>;
486b3f41edSDimitry Andric PHIInfoT PHIInfo;
496b3f41edSDimitry Andric
506b3f41edSDimitry Andric static unsigned phiInfoElementGetDest(PHIInfoElementT *Info);
516b3f41edSDimitry Andric static void phiInfoElementSetDef(PHIInfoElementT *Info, unsigned NewDef);
526b3f41edSDimitry Andric static PHISourcesT &phiInfoElementGetSources(PHIInfoElementT *Info);
536b3f41edSDimitry Andric static void phiInfoElementAddSource(PHIInfoElementT *Info, unsigned SourceReg,
546b3f41edSDimitry Andric MachineBasicBlock *SourceMBB);
556b3f41edSDimitry Andric static void phiInfoElementRemoveSource(PHIInfoElementT *Info,
566b3f41edSDimitry Andric unsigned SourceReg,
576b3f41edSDimitry Andric MachineBasicBlock *SourceMBB);
586b3f41edSDimitry Andric PHIInfoElementT *findPHIInfoElement(unsigned DestReg);
596b3f41edSDimitry Andric PHIInfoElementT *findPHIInfoElementFromSource(unsigned SourceReg,
606b3f41edSDimitry Andric MachineBasicBlock *SourceMBB);
616b3f41edSDimitry Andric
626b3f41edSDimitry Andric public:
636b3f41edSDimitry Andric bool findSourcesFromMBB(MachineBasicBlock *SourceMBB,
646b3f41edSDimitry Andric SmallVector<unsigned, 4> &Sources);
656b3f41edSDimitry Andric void addDest(unsigned DestReg, const DebugLoc &DL);
666b3f41edSDimitry Andric void replaceDef(unsigned OldDestReg, unsigned NewDestReg);
676b3f41edSDimitry Andric void deleteDef(unsigned DestReg);
686b3f41edSDimitry Andric void addSource(unsigned DestReg, unsigned SourceReg,
696b3f41edSDimitry Andric MachineBasicBlock *SourceMBB);
706b3f41edSDimitry Andric void removeSource(unsigned DestReg, unsigned SourceReg,
716b3f41edSDimitry Andric MachineBasicBlock *SourceMBB = nullptr);
726b3f41edSDimitry Andric bool findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB,
736b3f41edSDimitry Andric unsigned &DestReg);
746b3f41edSDimitry Andric bool isSource(unsigned Reg, MachineBasicBlock *SourceMBB = nullptr);
756b3f41edSDimitry Andric unsigned getNumSources(unsigned DestReg);
766b3f41edSDimitry Andric void dump(MachineRegisterInfo *MRI);
776b3f41edSDimitry Andric void clear();
786b3f41edSDimitry Andric
79044eb2f6SDimitry Andric using source_iterator = PHISourcesT::iterator;
80044eb2f6SDimitry Andric using dest_iterator = PHILinearizeDestIterator;
816b3f41edSDimitry Andric
826b3f41edSDimitry Andric dest_iterator dests_begin();
836b3f41edSDimitry Andric dest_iterator dests_end();
846b3f41edSDimitry Andric
856b3f41edSDimitry Andric source_iterator sources_begin(unsigned Reg);
866b3f41edSDimitry Andric source_iterator sources_end(unsigned Reg);
876b3f41edSDimitry Andric };
886b3f41edSDimitry Andric
896b3f41edSDimitry Andric class PHILinearizeDestIterator {
906b3f41edSDimitry Andric private:
916b3f41edSDimitry Andric PHILinearize::PHIInfoT::iterator Iter;
926b3f41edSDimitry Andric
936b3f41edSDimitry Andric public:
PHILinearizeDestIterator(PHILinearize::PHIInfoT::iterator I)94044eb2f6SDimitry Andric PHILinearizeDestIterator(PHILinearize::PHIInfoT::iterator I) : Iter(I) {}
95044eb2f6SDimitry Andric
operator *()966b3f41edSDimitry Andric unsigned operator*() { return PHILinearize::phiInfoElementGetDest(*Iter); }
operator ++()976b3f41edSDimitry Andric PHILinearizeDestIterator &operator++() {
986b3f41edSDimitry Andric ++Iter;
996b3f41edSDimitry Andric return *this;
1006b3f41edSDimitry Andric }
operator ==(const PHILinearizeDestIterator & I) const1016b3f41edSDimitry Andric bool operator==(const PHILinearizeDestIterator &I) const {
1026b3f41edSDimitry Andric return I.Iter == Iter;
1036b3f41edSDimitry Andric }
operator !=(const PHILinearizeDestIterator & I) const1046b3f41edSDimitry Andric bool operator!=(const PHILinearizeDestIterator &I) const {
1056b3f41edSDimitry Andric return I.Iter != Iter;
1066b3f41edSDimitry Andric }
1076b3f41edSDimitry Andric };
1086b3f41edSDimitry Andric
109044eb2f6SDimitry Andric } // end anonymous namespace
110044eb2f6SDimitry Andric
phiInfoElementGetDest(PHIInfoElementT * Info)1116b3f41edSDimitry Andric unsigned PHILinearize::phiInfoElementGetDest(PHIInfoElementT *Info) {
1126b3f41edSDimitry Andric return Info->DestReg;
1136b3f41edSDimitry Andric }
1146b3f41edSDimitry Andric
phiInfoElementSetDef(PHIInfoElementT * Info,unsigned NewDef)1156b3f41edSDimitry Andric void PHILinearize::phiInfoElementSetDef(PHIInfoElementT *Info,
1166b3f41edSDimitry Andric unsigned NewDef) {
1176b3f41edSDimitry Andric Info->DestReg = NewDef;
1186b3f41edSDimitry Andric }
1196b3f41edSDimitry Andric
1206b3f41edSDimitry Andric PHILinearize::PHISourcesT &
phiInfoElementGetSources(PHIInfoElementT * Info)1216b3f41edSDimitry Andric PHILinearize::phiInfoElementGetSources(PHIInfoElementT *Info) {
1226b3f41edSDimitry Andric return Info->Sources;
1236b3f41edSDimitry Andric }
1246b3f41edSDimitry Andric
phiInfoElementAddSource(PHIInfoElementT * Info,unsigned SourceReg,MachineBasicBlock * SourceMBB)1256b3f41edSDimitry Andric void PHILinearize::phiInfoElementAddSource(PHIInfoElementT *Info,
1266b3f41edSDimitry Andric unsigned SourceReg,
1276b3f41edSDimitry Andric MachineBasicBlock *SourceMBB) {
1286b3f41edSDimitry Andric // Assertion ensures we don't use the same SourceMBB for the
1296b3f41edSDimitry Andric // sources, because we cannot have different registers with
1306b3f41edSDimitry Andric // identical predecessors, but we can have the same register for
1316b3f41edSDimitry Andric // multiple predecessors.
1326b3f41edSDimitry Andric #if !defined(NDEBUG)
1336b3f41edSDimitry Andric for (auto SI : phiInfoElementGetSources(Info)) {
1346b3f41edSDimitry Andric assert((SI.second != SourceMBB || SourceReg == SI.first));
1356b3f41edSDimitry Andric }
1366b3f41edSDimitry Andric #endif
1376b3f41edSDimitry Andric
1386b3f41edSDimitry Andric phiInfoElementGetSources(Info).insert(PHISourceT(SourceReg, SourceMBB));
1396b3f41edSDimitry Andric }
1406b3f41edSDimitry Andric
phiInfoElementRemoveSource(PHIInfoElementT * Info,unsigned SourceReg,MachineBasicBlock * SourceMBB)1416b3f41edSDimitry Andric void PHILinearize::phiInfoElementRemoveSource(PHIInfoElementT *Info,
1426b3f41edSDimitry Andric unsigned SourceReg,
1436b3f41edSDimitry Andric MachineBasicBlock *SourceMBB) {
1446b3f41edSDimitry Andric auto &Sources = phiInfoElementGetSources(Info);
1456b3f41edSDimitry Andric SmallVector<PHISourceT, 4> ElimiatedSources;
1466b3f41edSDimitry Andric for (auto SI : Sources) {
1476b3f41edSDimitry Andric if (SI.first == SourceReg &&
1486b3f41edSDimitry Andric (SI.second == nullptr || SI.second == SourceMBB)) {
1496b3f41edSDimitry Andric ElimiatedSources.push_back(PHISourceT(SI.first, SI.second));
1506b3f41edSDimitry Andric }
1516b3f41edSDimitry Andric }
1526b3f41edSDimitry Andric
1536b3f41edSDimitry Andric for (auto &Source : ElimiatedSources) {
1546b3f41edSDimitry Andric Sources.erase(Source);
1556b3f41edSDimitry Andric }
1566b3f41edSDimitry Andric }
1576b3f41edSDimitry Andric
1586b3f41edSDimitry Andric PHILinearize::PHIInfoElementT *
findPHIInfoElement(unsigned DestReg)1596b3f41edSDimitry Andric PHILinearize::findPHIInfoElement(unsigned DestReg) {
160e3b55780SDimitry Andric for (auto *I : PHIInfo) {
1616b3f41edSDimitry Andric if (phiInfoElementGetDest(I) == DestReg) {
1626b3f41edSDimitry Andric return I;
1636b3f41edSDimitry Andric }
1646b3f41edSDimitry Andric }
1656b3f41edSDimitry Andric return nullptr;
1666b3f41edSDimitry Andric }
1676b3f41edSDimitry Andric
1686b3f41edSDimitry Andric PHILinearize::PHIInfoElementT *
findPHIInfoElementFromSource(unsigned SourceReg,MachineBasicBlock * SourceMBB)1696b3f41edSDimitry Andric PHILinearize::findPHIInfoElementFromSource(unsigned SourceReg,
1706b3f41edSDimitry Andric MachineBasicBlock *SourceMBB) {
171e3b55780SDimitry Andric for (auto *I : PHIInfo) {
1726b3f41edSDimitry Andric for (auto SI : phiInfoElementGetSources(I)) {
1736b3f41edSDimitry Andric if (SI.first == SourceReg &&
1746b3f41edSDimitry Andric (SI.second == nullptr || SI.second == SourceMBB)) {
1756b3f41edSDimitry Andric return I;
1766b3f41edSDimitry Andric }
1776b3f41edSDimitry Andric }
1786b3f41edSDimitry Andric }
1796b3f41edSDimitry Andric return nullptr;
1806b3f41edSDimitry Andric }
1816b3f41edSDimitry Andric
findSourcesFromMBB(MachineBasicBlock * SourceMBB,SmallVector<unsigned,4> & Sources)1826b3f41edSDimitry Andric bool PHILinearize::findSourcesFromMBB(MachineBasicBlock *SourceMBB,
1836b3f41edSDimitry Andric SmallVector<unsigned, 4> &Sources) {
1846b3f41edSDimitry Andric bool FoundSource = false;
185e3b55780SDimitry Andric for (auto *I : PHIInfo) {
1866b3f41edSDimitry Andric for (auto SI : phiInfoElementGetSources(I)) {
1876b3f41edSDimitry Andric if (SI.second == SourceMBB) {
1886b3f41edSDimitry Andric FoundSource = true;
1896b3f41edSDimitry Andric Sources.push_back(SI.first);
1906b3f41edSDimitry Andric }
1916b3f41edSDimitry Andric }
1926b3f41edSDimitry Andric }
1936b3f41edSDimitry Andric return FoundSource;
1946b3f41edSDimitry Andric }
1956b3f41edSDimitry Andric
addDest(unsigned DestReg,const DebugLoc & DL)1966b3f41edSDimitry Andric void PHILinearize::addDest(unsigned DestReg, const DebugLoc &DL) {
197c0981da4SDimitry Andric assert(findPHIInfoElement(DestReg) == nullptr && "Dest already exists");
1986b3f41edSDimitry Andric PHISourcesT EmptySet;
1996b3f41edSDimitry Andric PHIInfoElementT *NewElement = new PHIInfoElementT();
2006b3f41edSDimitry Andric NewElement->DestReg = DestReg;
2016b3f41edSDimitry Andric NewElement->DL = DL;
2026b3f41edSDimitry Andric NewElement->Sources = EmptySet;
2036b3f41edSDimitry Andric PHIInfo.insert(NewElement);
2046b3f41edSDimitry Andric }
2056b3f41edSDimitry Andric
replaceDef(unsigned OldDestReg,unsigned NewDestReg)2066b3f41edSDimitry Andric void PHILinearize::replaceDef(unsigned OldDestReg, unsigned NewDestReg) {
2076b3f41edSDimitry Andric phiInfoElementSetDef(findPHIInfoElement(OldDestReg), NewDestReg);
2086b3f41edSDimitry Andric }
2096b3f41edSDimitry Andric
deleteDef(unsigned DestReg)2106b3f41edSDimitry Andric void PHILinearize::deleteDef(unsigned DestReg) {
2116b3f41edSDimitry Andric PHIInfoElementT *InfoElement = findPHIInfoElement(DestReg);
2126b3f41edSDimitry Andric PHIInfo.erase(InfoElement);
2136b3f41edSDimitry Andric delete InfoElement;
2146b3f41edSDimitry Andric }
2156b3f41edSDimitry Andric
addSource(unsigned DestReg,unsigned SourceReg,MachineBasicBlock * SourceMBB)2166b3f41edSDimitry Andric void PHILinearize::addSource(unsigned DestReg, unsigned SourceReg,
2176b3f41edSDimitry Andric MachineBasicBlock *SourceMBB) {
2186b3f41edSDimitry Andric phiInfoElementAddSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB);
2196b3f41edSDimitry Andric }
2206b3f41edSDimitry Andric
removeSource(unsigned DestReg,unsigned SourceReg,MachineBasicBlock * SourceMBB)2216b3f41edSDimitry Andric void PHILinearize::removeSource(unsigned DestReg, unsigned SourceReg,
2226b3f41edSDimitry Andric MachineBasicBlock *SourceMBB) {
2236b3f41edSDimitry Andric phiInfoElementRemoveSource(findPHIInfoElement(DestReg), SourceReg, SourceMBB);
2246b3f41edSDimitry Andric }
2256b3f41edSDimitry Andric
findDest(unsigned SourceReg,MachineBasicBlock * SourceMBB,unsigned & DestReg)2266b3f41edSDimitry Andric bool PHILinearize::findDest(unsigned SourceReg, MachineBasicBlock *SourceMBB,
2276b3f41edSDimitry Andric unsigned &DestReg) {
2286b3f41edSDimitry Andric PHIInfoElementT *InfoElement =
2296b3f41edSDimitry Andric findPHIInfoElementFromSource(SourceReg, SourceMBB);
2306b3f41edSDimitry Andric if (InfoElement != nullptr) {
2316b3f41edSDimitry Andric DestReg = phiInfoElementGetDest(InfoElement);
2326b3f41edSDimitry Andric return true;
2336b3f41edSDimitry Andric }
2346b3f41edSDimitry Andric return false;
2356b3f41edSDimitry Andric }
2366b3f41edSDimitry Andric
isSource(unsigned Reg,MachineBasicBlock * SourceMBB)2376b3f41edSDimitry Andric bool PHILinearize::isSource(unsigned Reg, MachineBasicBlock *SourceMBB) {
2386b3f41edSDimitry Andric unsigned DestReg;
2396b3f41edSDimitry Andric return findDest(Reg, SourceMBB, DestReg);
2406b3f41edSDimitry Andric }
2416b3f41edSDimitry Andric
getNumSources(unsigned DestReg)2426b3f41edSDimitry Andric unsigned PHILinearize::getNumSources(unsigned DestReg) {
2436b3f41edSDimitry Andric return phiInfoElementGetSources(findPHIInfoElement(DestReg)).size();
2446b3f41edSDimitry Andric }
2456b3f41edSDimitry Andric
246044eb2f6SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump(MachineRegisterInfo * MRI)247044eb2f6SDimitry Andric LLVM_DUMP_METHOD void PHILinearize::dump(MachineRegisterInfo *MRI) {
2486b3f41edSDimitry Andric const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
2496b3f41edSDimitry Andric dbgs() << "=PHIInfo Start=\n";
250e3b55780SDimitry Andric for (auto *PII : this->PHIInfo) {
2516b3f41edSDimitry Andric PHIInfoElementT &Element = *PII;
252044eb2f6SDimitry Andric dbgs() << "Dest: " << printReg(Element.DestReg, TRI)
2536b3f41edSDimitry Andric << " Sources: {";
2546b3f41edSDimitry Andric for (auto &SI : Element.Sources) {
255044eb2f6SDimitry Andric dbgs() << printReg(SI.first, TRI) << '(' << printMBBReference(*SI.second)
256044eb2f6SDimitry Andric << "),";
2576b3f41edSDimitry Andric }
2586b3f41edSDimitry Andric dbgs() << "}\n";
2596b3f41edSDimitry Andric }
2606b3f41edSDimitry Andric dbgs() << "=PHIInfo End=\n";
2616b3f41edSDimitry Andric }
262044eb2f6SDimitry Andric #endif
2636b3f41edSDimitry Andric
clear()2646b3f41edSDimitry Andric void PHILinearize::clear() { PHIInfo = PHIInfoT(); }
2656b3f41edSDimitry Andric
dests_begin()2666b3f41edSDimitry Andric PHILinearize::dest_iterator PHILinearize::dests_begin() {
2676b3f41edSDimitry Andric return PHILinearizeDestIterator(PHIInfo.begin());
2686b3f41edSDimitry Andric }
2696b3f41edSDimitry Andric
dests_end()2706b3f41edSDimitry Andric PHILinearize::dest_iterator PHILinearize::dests_end() {
2716b3f41edSDimitry Andric return PHILinearizeDestIterator(PHIInfo.end());
2726b3f41edSDimitry Andric }
2736b3f41edSDimitry Andric
sources_begin(unsigned Reg)2746b3f41edSDimitry Andric PHILinearize::source_iterator PHILinearize::sources_begin(unsigned Reg) {
2756b3f41edSDimitry Andric auto InfoElement = findPHIInfoElement(Reg);
2766b3f41edSDimitry Andric return phiInfoElementGetSources(InfoElement).begin();
2776b3f41edSDimitry Andric }
278044eb2f6SDimitry Andric
sources_end(unsigned Reg)2796b3f41edSDimitry Andric PHILinearize::source_iterator PHILinearize::sources_end(unsigned Reg) {
2806b3f41edSDimitry Andric auto InfoElement = findPHIInfoElement(Reg);
2816b3f41edSDimitry Andric return phiInfoElementGetSources(InfoElement).end();
2826b3f41edSDimitry Andric }
2836b3f41edSDimitry Andric
getPHINumInputs(MachineInstr & PHI)2846b3f41edSDimitry Andric static unsigned getPHINumInputs(MachineInstr &PHI) {
2856b3f41edSDimitry Andric assert(PHI.isPHI());
2866b3f41edSDimitry Andric return (PHI.getNumOperands() - 1) / 2;
2876b3f41edSDimitry Andric }
2886b3f41edSDimitry Andric
getPHIPred(MachineInstr & PHI,unsigned Index)2896b3f41edSDimitry Andric static MachineBasicBlock *getPHIPred(MachineInstr &PHI, unsigned Index) {
2906b3f41edSDimitry Andric assert(PHI.isPHI());
2916b3f41edSDimitry Andric return PHI.getOperand(Index * 2 + 2).getMBB();
2926b3f41edSDimitry Andric }
2936b3f41edSDimitry Andric
setPhiPred(MachineInstr & PHI,unsigned Index,MachineBasicBlock * NewPred)2946b3f41edSDimitry Andric static void setPhiPred(MachineInstr &PHI, unsigned Index,
2956b3f41edSDimitry Andric MachineBasicBlock *NewPred) {
2966b3f41edSDimitry Andric PHI.getOperand(Index * 2 + 2).setMBB(NewPred);
2976b3f41edSDimitry Andric }
2986b3f41edSDimitry Andric
getPHISourceReg(MachineInstr & PHI,unsigned Index)2996b3f41edSDimitry Andric static unsigned getPHISourceReg(MachineInstr &PHI, unsigned Index) {
3006b3f41edSDimitry Andric assert(PHI.isPHI());
3016b3f41edSDimitry Andric return PHI.getOperand(Index * 2 + 1).getReg();
3026b3f41edSDimitry Andric }
3036b3f41edSDimitry Andric
getPHIDestReg(MachineInstr & PHI)3046b3f41edSDimitry Andric static unsigned getPHIDestReg(MachineInstr &PHI) {
3056b3f41edSDimitry Andric assert(PHI.isPHI());
3066b3f41edSDimitry Andric return PHI.getOperand(0).getReg();
3076b3f41edSDimitry Andric }
3086b3f41edSDimitry Andric
309044eb2f6SDimitry Andric namespace {
310044eb2f6SDimitry Andric
311044eb2f6SDimitry Andric class RegionMRT;
312044eb2f6SDimitry Andric class MBBMRT;
313044eb2f6SDimitry Andric
3146b3f41edSDimitry Andric class LinearizedRegion {
3156b3f41edSDimitry Andric protected:
3166b3f41edSDimitry Andric MachineBasicBlock *Entry;
3176b3f41edSDimitry Andric // The exit block is part of the region, and is the last
3186b3f41edSDimitry Andric // merge block before exiting the region.
3196b3f41edSDimitry Andric MachineBasicBlock *Exit;
3206b3f41edSDimitry Andric DenseSet<unsigned> LiveOuts;
3216b3f41edSDimitry Andric SmallPtrSet<MachineBasicBlock *, 1> MBBs;
3226b3f41edSDimitry Andric bool HasLoop;
3236b3f41edSDimitry Andric LinearizedRegion *Parent;
3246b3f41edSDimitry Andric RegionMRT *RMRT;
3256b3f41edSDimitry Andric
326b60736ecSDimitry Andric void storeLiveOutReg(MachineBasicBlock *MBB, Register Reg,
3276b3f41edSDimitry Andric MachineInstr *DefInstr, const MachineRegisterInfo *MRI,
3286b3f41edSDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo);
3296b3f41edSDimitry Andric
330b60736ecSDimitry Andric void storeLiveOutRegRegion(RegionMRT *Region, Register Reg,
3316b3f41edSDimitry Andric MachineInstr *DefInstr,
3326b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
3336b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
3346b3f41edSDimitry Andric PHILinearize &PHIInfo);
3356b3f41edSDimitry Andric
3366b3f41edSDimitry Andric void storeMBBLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI,
3376b3f41edSDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo,
3386b3f41edSDimitry Andric RegionMRT *TopRegion);
3396b3f41edSDimitry Andric
3406b3f41edSDimitry Andric void storeLiveOuts(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI,
3416b3f41edSDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo);
3426b3f41edSDimitry Andric
3436b3f41edSDimitry Andric void storeLiveOuts(RegionMRT *Region, const MachineRegisterInfo *MRI,
3446b3f41edSDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo,
3456b3f41edSDimitry Andric RegionMRT *TopRegion = nullptr);
3466b3f41edSDimitry Andric
3476b3f41edSDimitry Andric public:
348044eb2f6SDimitry Andric LinearizedRegion();
349044eb2f6SDimitry Andric LinearizedRegion(MachineBasicBlock *MBB, const MachineRegisterInfo *MRI,
350044eb2f6SDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo);
351044eb2f6SDimitry Andric ~LinearizedRegion() = default;
352044eb2f6SDimitry Andric
setRegionMRT(RegionMRT * Region)3536b3f41edSDimitry Andric void setRegionMRT(RegionMRT *Region) { RMRT = Region; }
3546b3f41edSDimitry Andric
getRegionMRT()3556b3f41edSDimitry Andric RegionMRT *getRegionMRT() { return RMRT; }
3566b3f41edSDimitry Andric
setParent(LinearizedRegion * P)3576b3f41edSDimitry Andric void setParent(LinearizedRegion *P) { Parent = P; }
3586b3f41edSDimitry Andric
getParent()3596b3f41edSDimitry Andric LinearizedRegion *getParent() { return Parent; }
3606b3f41edSDimitry Andric
3616b3f41edSDimitry Andric void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr);
3626b3f41edSDimitry Andric
3636b3f41edSDimitry Andric void setBBSelectRegIn(unsigned Reg);
3646b3f41edSDimitry Andric
3656b3f41edSDimitry Andric unsigned getBBSelectRegIn();
3666b3f41edSDimitry Andric
3676b3f41edSDimitry Andric void setBBSelectRegOut(unsigned Reg, bool IsLiveOut);
3686b3f41edSDimitry Andric
3696b3f41edSDimitry Andric unsigned getBBSelectRegOut();
3706b3f41edSDimitry Andric
3716b3f41edSDimitry Andric void setHasLoop(bool Value);
3726b3f41edSDimitry Andric
3736b3f41edSDimitry Andric bool getHasLoop();
3746b3f41edSDimitry Andric
3756b3f41edSDimitry Andric void addLiveOut(unsigned VReg);
3766b3f41edSDimitry Andric
3776b3f41edSDimitry Andric void removeLiveOut(unsigned Reg);
3786b3f41edSDimitry Andric
3796b3f41edSDimitry Andric void replaceLiveOut(unsigned OldReg, unsigned NewReg);
3806b3f41edSDimitry Andric
381b60736ecSDimitry Andric void replaceRegister(unsigned Register, class Register NewRegister,
3826b3f41edSDimitry Andric MachineRegisterInfo *MRI, bool ReplaceInside,
3836b3f41edSDimitry Andric bool ReplaceOutside, bool IncludeLoopPHIs);
3846b3f41edSDimitry Andric
3856b3f41edSDimitry Andric void replaceRegisterInsideRegion(unsigned Register, unsigned NewRegister,
3866b3f41edSDimitry Andric bool IncludeLoopPHIs,
3876b3f41edSDimitry Andric MachineRegisterInfo *MRI);
3886b3f41edSDimitry Andric
3896b3f41edSDimitry Andric void replaceRegisterOutsideRegion(unsigned Register, unsigned NewRegister,
3906b3f41edSDimitry Andric bool IncludeLoopPHIs,
3916b3f41edSDimitry Andric MachineRegisterInfo *MRI);
3926b3f41edSDimitry Andric
3936b3f41edSDimitry Andric DenseSet<unsigned> *getLiveOuts();
3946b3f41edSDimitry Andric
3956b3f41edSDimitry Andric void setEntry(MachineBasicBlock *NewEntry);
3966b3f41edSDimitry Andric
3976b3f41edSDimitry Andric MachineBasicBlock *getEntry();
3986b3f41edSDimitry Andric
3996b3f41edSDimitry Andric void setExit(MachineBasicBlock *NewExit);
4006b3f41edSDimitry Andric
4016b3f41edSDimitry Andric MachineBasicBlock *getExit();
4026b3f41edSDimitry Andric
4036b3f41edSDimitry Andric void addMBB(MachineBasicBlock *MBB);
4046b3f41edSDimitry Andric
4056b3f41edSDimitry Andric void addMBBs(LinearizedRegion *InnerRegion);
4066b3f41edSDimitry Andric
4076b3f41edSDimitry Andric bool contains(MachineBasicBlock *MBB);
4086b3f41edSDimitry Andric
4096b3f41edSDimitry Andric bool isLiveOut(unsigned Reg);
4106b3f41edSDimitry Andric
4116b3f41edSDimitry Andric bool hasNoDef(unsigned Reg, MachineRegisterInfo *MRI);
4126b3f41edSDimitry Andric
4136b3f41edSDimitry Andric void removeFalseRegisterKills(MachineRegisterInfo *MRI);
4146b3f41edSDimitry Andric
4156b3f41edSDimitry Andric void initLiveOut(RegionMRT *Region, const MachineRegisterInfo *MRI,
4166b3f41edSDimitry Andric const TargetRegisterInfo *TRI, PHILinearize &PHIInfo);
4176b3f41edSDimitry Andric };
4186b3f41edSDimitry Andric
4196b3f41edSDimitry Andric class MRT {
4206b3f41edSDimitry Andric protected:
4216b3f41edSDimitry Andric RegionMRT *Parent;
4226b3f41edSDimitry Andric unsigned BBSelectRegIn;
4236b3f41edSDimitry Andric unsigned BBSelectRegOut;
4246b3f41edSDimitry Andric
4256b3f41edSDimitry Andric public:
426044eb2f6SDimitry Andric virtual ~MRT() = default;
427044eb2f6SDimitry Andric
getBBSelectRegIn()4286b3f41edSDimitry Andric unsigned getBBSelectRegIn() { return BBSelectRegIn; }
4296b3f41edSDimitry Andric
getBBSelectRegOut()4306b3f41edSDimitry Andric unsigned getBBSelectRegOut() { return BBSelectRegOut; }
4316b3f41edSDimitry Andric
setBBSelectRegIn(unsigned Reg)4326b3f41edSDimitry Andric void setBBSelectRegIn(unsigned Reg) { BBSelectRegIn = Reg; }
4336b3f41edSDimitry Andric
setBBSelectRegOut(unsigned Reg)4346b3f41edSDimitry Andric void setBBSelectRegOut(unsigned Reg) { BBSelectRegOut = Reg; }
4356b3f41edSDimitry Andric
getRegionMRT()4366b3f41edSDimitry Andric virtual RegionMRT *getRegionMRT() { return nullptr; }
4376b3f41edSDimitry Andric
getMBBMRT()4386b3f41edSDimitry Andric virtual MBBMRT *getMBBMRT() { return nullptr; }
4396b3f41edSDimitry Andric
isRegion()4406b3f41edSDimitry Andric bool isRegion() { return getRegionMRT() != nullptr; }
4416b3f41edSDimitry Andric
isMBB()4426b3f41edSDimitry Andric bool isMBB() { return getMBBMRT() != nullptr; }
4436b3f41edSDimitry Andric
isRoot()4446b3f41edSDimitry Andric bool isRoot() { return Parent == nullptr; }
4456b3f41edSDimitry Andric
setParent(RegionMRT * Region)4466b3f41edSDimitry Andric void setParent(RegionMRT *Region) { Parent = Region; }
4476b3f41edSDimitry Andric
getParent()4486b3f41edSDimitry Andric RegionMRT *getParent() { return Parent; }
4496b3f41edSDimitry Andric
4506b3f41edSDimitry Andric static MachineBasicBlock *
4516b3f41edSDimitry Andric initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo,
4526b3f41edSDimitry Andric DenseMap<MachineRegion *, RegionMRT *> &RegionMap);
4536b3f41edSDimitry Andric
4546b3f41edSDimitry Andric static RegionMRT *buildMRT(MachineFunction &MF,
4556b3f41edSDimitry Andric const MachineRegionInfo *RegionInfo,
4566b3f41edSDimitry Andric const SIInstrInfo *TII,
4576b3f41edSDimitry Andric MachineRegisterInfo *MRI);
4586b3f41edSDimitry Andric
4596b3f41edSDimitry Andric virtual void dump(const TargetRegisterInfo *TRI, int depth = 0) = 0;
4606b3f41edSDimitry Andric
dumpDepth(int depth)4616b3f41edSDimitry Andric void dumpDepth(int depth) {
4626b3f41edSDimitry Andric for (int i = depth; i > 0; --i) {
4636b3f41edSDimitry Andric dbgs() << " ";
4646b3f41edSDimitry Andric }
4656b3f41edSDimitry Andric }
4666b3f41edSDimitry Andric };
4676b3f41edSDimitry Andric
4686b3f41edSDimitry Andric class MBBMRT : public MRT {
4696b3f41edSDimitry Andric MachineBasicBlock *MBB;
4706b3f41edSDimitry Andric
4716b3f41edSDimitry Andric public:
MBBMRT(MachineBasicBlock * BB)4726b3f41edSDimitry Andric MBBMRT(MachineBasicBlock *BB) : MBB(BB) {
4736b3f41edSDimitry Andric setParent(nullptr);
4746b3f41edSDimitry Andric setBBSelectRegOut(0);
4756b3f41edSDimitry Andric setBBSelectRegIn(0);
4766b3f41edSDimitry Andric }
477044eb2f6SDimitry Andric
getMBBMRT()478044eb2f6SDimitry Andric MBBMRT *getMBBMRT() override { return this; }
479044eb2f6SDimitry Andric
getMBB()480044eb2f6SDimitry Andric MachineBasicBlock *getMBB() { return MBB; }
481044eb2f6SDimitry Andric
dump(const TargetRegisterInfo * TRI,int depth=0)482044eb2f6SDimitry Andric void dump(const TargetRegisterInfo *TRI, int depth = 0) override {
483044eb2f6SDimitry Andric dumpDepth(depth);
484044eb2f6SDimitry Andric dbgs() << "MBB: " << getMBB()->getNumber();
485044eb2f6SDimitry Andric dbgs() << " In: " << printReg(getBBSelectRegIn(), TRI);
486044eb2f6SDimitry Andric dbgs() << ", Out: " << printReg(getBBSelectRegOut(), TRI) << "\n";
487044eb2f6SDimitry Andric }
4886b3f41edSDimitry Andric };
4896b3f41edSDimitry Andric
4906b3f41edSDimitry Andric class RegionMRT : public MRT {
4916b3f41edSDimitry Andric protected:
4926b3f41edSDimitry Andric MachineRegion *Region;
493044eb2f6SDimitry Andric LinearizedRegion *LRegion = nullptr;
494044eb2f6SDimitry Andric MachineBasicBlock *Succ = nullptr;
4956b3f41edSDimitry Andric SetVector<MRT *> Children;
4966b3f41edSDimitry Andric
4976b3f41edSDimitry Andric public:
RegionMRT(MachineRegion * MachineRegion)498044eb2f6SDimitry Andric RegionMRT(MachineRegion *MachineRegion) : Region(MachineRegion) {
499044eb2f6SDimitry Andric setParent(nullptr);
500044eb2f6SDimitry Andric setBBSelectRegOut(0);
501044eb2f6SDimitry Andric setBBSelectRegIn(0);
502044eb2f6SDimitry Andric }
503044eb2f6SDimitry Andric
~RegionMRT()504044eb2f6SDimitry Andric ~RegionMRT() override {
505044eb2f6SDimitry Andric if (LRegion) {
506044eb2f6SDimitry Andric delete LRegion;
507044eb2f6SDimitry Andric }
508044eb2f6SDimitry Andric
509e3b55780SDimitry Andric for (auto *CI : Children) {
510044eb2f6SDimitry Andric delete &(*CI);
511044eb2f6SDimitry Andric }
512044eb2f6SDimitry Andric }
513044eb2f6SDimitry Andric
getRegionMRT()514044eb2f6SDimitry Andric RegionMRT *getRegionMRT() override { return this; }
5156b3f41edSDimitry Andric
setLinearizedRegion(LinearizedRegion * LinearizeRegion)5166b3f41edSDimitry Andric void setLinearizedRegion(LinearizedRegion *LinearizeRegion) {
5176b3f41edSDimitry Andric LRegion = LinearizeRegion;
5186b3f41edSDimitry Andric }
5196b3f41edSDimitry Andric
getLinearizedRegion()5206b3f41edSDimitry Andric LinearizedRegion *getLinearizedRegion() { return LRegion; }
5216b3f41edSDimitry Andric
getMachineRegion()5226b3f41edSDimitry Andric MachineRegion *getMachineRegion() { return Region; }
5236b3f41edSDimitry Andric
getInnerOutputRegister()5246b3f41edSDimitry Andric unsigned getInnerOutputRegister() {
5256b3f41edSDimitry Andric return (*(Children.begin()))->getBBSelectRegOut();
5266b3f41edSDimitry Andric }
5276b3f41edSDimitry Andric
addChild(MRT * Tree)5286b3f41edSDimitry Andric void addChild(MRT *Tree) { Children.insert(Tree); }
5296b3f41edSDimitry Andric
getChildren()5306b3f41edSDimitry Andric SetVector<MRT *> *getChildren() { return &Children; }
5316b3f41edSDimitry Andric
dump(const TargetRegisterInfo * TRI,int depth=0)532044eb2f6SDimitry Andric void dump(const TargetRegisterInfo *TRI, int depth = 0) override {
5336b3f41edSDimitry Andric dumpDepth(depth);
5346b3f41edSDimitry Andric dbgs() << "Region: " << (void *)Region;
535044eb2f6SDimitry Andric dbgs() << " In: " << printReg(getBBSelectRegIn(), TRI);
536044eb2f6SDimitry Andric dbgs() << ", Out: " << printReg(getBBSelectRegOut(), TRI) << "\n";
5376b3f41edSDimitry Andric
5386b3f41edSDimitry Andric dumpDepth(depth);
5396b3f41edSDimitry Andric if (getSucc())
5406b3f41edSDimitry Andric dbgs() << "Succ: " << getSucc()->getNumber() << "\n";
5416b3f41edSDimitry Andric else
5426b3f41edSDimitry Andric dbgs() << "Succ: none \n";
543e3b55780SDimitry Andric for (auto *MRTI : Children) {
5446b3f41edSDimitry Andric MRTI->dump(TRI, depth + 1);
5456b3f41edSDimitry Andric }
5466b3f41edSDimitry Andric }
5476b3f41edSDimitry Andric
getEntryTree()5486b3f41edSDimitry Andric MRT *getEntryTree() { return Children.back(); }
5496b3f41edSDimitry Andric
getExitTree()5506b3f41edSDimitry Andric MRT *getExitTree() { return Children.front(); }
5516b3f41edSDimitry Andric
getEntry()5526b3f41edSDimitry Andric MachineBasicBlock *getEntry() {
5536b3f41edSDimitry Andric MRT *Tree = Children.back();
5546b3f41edSDimitry Andric return (Tree->isRegion()) ? Tree->getRegionMRT()->getEntry()
5556b3f41edSDimitry Andric : Tree->getMBBMRT()->getMBB();
5566b3f41edSDimitry Andric }
5576b3f41edSDimitry Andric
getExit()5586b3f41edSDimitry Andric MachineBasicBlock *getExit() {
5596b3f41edSDimitry Andric MRT *Tree = Children.front();
5606b3f41edSDimitry Andric return (Tree->isRegion()) ? Tree->getRegionMRT()->getExit()
5616b3f41edSDimitry Andric : Tree->getMBBMRT()->getMBB();
5626b3f41edSDimitry Andric }
5636b3f41edSDimitry Andric
setSucc(MachineBasicBlock * MBB)5646b3f41edSDimitry Andric void setSucc(MachineBasicBlock *MBB) { Succ = MBB; }
5656b3f41edSDimitry Andric
getSucc()5666b3f41edSDimitry Andric MachineBasicBlock *getSucc() { return Succ; }
5676b3f41edSDimitry Andric
contains(MachineBasicBlock * MBB)5686b3f41edSDimitry Andric bool contains(MachineBasicBlock *MBB) {
569e3b55780SDimitry Andric for (auto *CI : Children) {
5706b3f41edSDimitry Andric if (CI->isMBB()) {
571ac9a064cSDimitry Andric if (MBB == CI->getMBBMRT()->getMBB())
5726b3f41edSDimitry Andric return true;
5736b3f41edSDimitry Andric } else {
574ac9a064cSDimitry Andric if (CI->getRegionMRT()->contains(MBB))
5756b3f41edSDimitry Andric return true;
576ac9a064cSDimitry Andric if (CI->getRegionMRT()->getLinearizedRegion() != nullptr &&
577ac9a064cSDimitry Andric CI->getRegionMRT()->getLinearizedRegion()->contains(MBB))
5786b3f41edSDimitry Andric return true;
5796b3f41edSDimitry Andric }
5806b3f41edSDimitry Andric }
5816b3f41edSDimitry Andric return false;
5826b3f41edSDimitry Andric }
5836b3f41edSDimitry Andric
replaceLiveOutReg(unsigned Register,unsigned NewRegister)5846b3f41edSDimitry Andric void replaceLiveOutReg(unsigned Register, unsigned NewRegister) {
5856b3f41edSDimitry Andric LinearizedRegion *LRegion = getLinearizedRegion();
5866b3f41edSDimitry Andric LRegion->replaceLiveOut(Register, NewRegister);
5876b3f41edSDimitry Andric for (auto &CI : Children) {
5886b3f41edSDimitry Andric if (CI->isRegion()) {
5896b3f41edSDimitry Andric CI->getRegionMRT()->replaceLiveOutReg(Register, NewRegister);
5906b3f41edSDimitry Andric }
5916b3f41edSDimitry Andric }
5926b3f41edSDimitry Andric }
5936b3f41edSDimitry Andric };
5946b3f41edSDimitry Andric
595044eb2f6SDimitry Andric } // end anonymous namespace
596044eb2f6SDimitry Andric
createBBSelectReg(const SIInstrInfo * TII,MachineRegisterInfo * MRI)5976b3f41edSDimitry Andric static unsigned createBBSelectReg(const SIInstrInfo *TII,
5986b3f41edSDimitry Andric MachineRegisterInfo *MRI) {
5996b3f41edSDimitry Andric return MRI->createVirtualRegister(TII->getPreferredSelectRegClass(32));
6006b3f41edSDimitry Andric }
6016b3f41edSDimitry Andric
6026b3f41edSDimitry Andric MachineBasicBlock *
initializeMRT(MachineFunction & MF,const MachineRegionInfo * RegionInfo,DenseMap<MachineRegion *,RegionMRT * > & RegionMap)6036b3f41edSDimitry Andric MRT::initializeMRT(MachineFunction &MF, const MachineRegionInfo *RegionInfo,
6046b3f41edSDimitry Andric DenseMap<MachineRegion *, RegionMRT *> &RegionMap) {
6056b3f41edSDimitry Andric for (auto &MFI : MF) {
6066b3f41edSDimitry Andric MachineBasicBlock *ExitMBB = &MFI;
607c0981da4SDimitry Andric if (ExitMBB->succ_empty()) {
6086b3f41edSDimitry Andric return ExitMBB;
6096b3f41edSDimitry Andric }
6106b3f41edSDimitry Andric }
6116b3f41edSDimitry Andric llvm_unreachable("CFG has no exit block");
6126b3f41edSDimitry Andric return nullptr;
6136b3f41edSDimitry Andric }
6146b3f41edSDimitry Andric
buildMRT(MachineFunction & MF,const MachineRegionInfo * RegionInfo,const SIInstrInfo * TII,MachineRegisterInfo * MRI)6156b3f41edSDimitry Andric RegionMRT *MRT::buildMRT(MachineFunction &MF,
6166b3f41edSDimitry Andric const MachineRegionInfo *RegionInfo,
6176b3f41edSDimitry Andric const SIInstrInfo *TII, MachineRegisterInfo *MRI) {
6186b3f41edSDimitry Andric SmallPtrSet<MachineRegion *, 4> PlacedRegions;
6196b3f41edSDimitry Andric DenseMap<MachineRegion *, RegionMRT *> RegionMap;
6206b3f41edSDimitry Andric MachineRegion *TopLevelRegion = RegionInfo->getTopLevelRegion();
6216b3f41edSDimitry Andric RegionMRT *Result = new RegionMRT(TopLevelRegion);
6226b3f41edSDimitry Andric RegionMap[TopLevelRegion] = Result;
6236b3f41edSDimitry Andric
6246b3f41edSDimitry Andric // Insert the exit block first, we need it to be the merge node
6256b3f41edSDimitry Andric // for the top level region.
6266b3f41edSDimitry Andric MachineBasicBlock *Exit = initializeMRT(MF, RegionInfo, RegionMap);
6276b3f41edSDimitry Andric
6286b3f41edSDimitry Andric unsigned BBSelectRegIn = createBBSelectReg(TII, MRI);
6296b3f41edSDimitry Andric MBBMRT *ExitMRT = new MBBMRT(Exit);
6306b3f41edSDimitry Andric RegionMap[RegionInfo->getRegionFor(Exit)]->addChild(ExitMRT);
6316b3f41edSDimitry Andric ExitMRT->setBBSelectRegIn(BBSelectRegIn);
6326b3f41edSDimitry Andric
633e3b55780SDimitry Andric for (auto *MBBI : post_order(&(MF.front()))) {
6346b3f41edSDimitry Andric MachineBasicBlock *MBB = &(*MBBI);
6356b3f41edSDimitry Andric
6366b3f41edSDimitry Andric // Skip Exit since we already added it
6376b3f41edSDimitry Andric if (MBB == Exit) {
6386b3f41edSDimitry Andric continue;
6396b3f41edSDimitry Andric }
6406b3f41edSDimitry Andric
641eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting " << printMBBReference(*MBB) << "\n");
6426b3f41edSDimitry Andric MBBMRT *NewMBB = new MBBMRT(MBB);
6436b3f41edSDimitry Andric MachineRegion *Region = RegionInfo->getRegionFor(MBB);
6446b3f41edSDimitry Andric
6456b3f41edSDimitry Andric // Ensure we have the MRT region
6466b3f41edSDimitry Andric if (RegionMap.count(Region) == 0) {
6476b3f41edSDimitry Andric RegionMRT *NewMRTRegion = new RegionMRT(Region);
6486b3f41edSDimitry Andric RegionMap[Region] = NewMRTRegion;
6496b3f41edSDimitry Andric
6506b3f41edSDimitry Andric // Ensure all parents are in the RegionMap
6516b3f41edSDimitry Andric MachineRegion *Parent = Region->getParent();
6526b3f41edSDimitry Andric while (RegionMap.count(Parent) == 0) {
6536b3f41edSDimitry Andric RegionMRT *NewMRTParent = new RegionMRT(Parent);
6546b3f41edSDimitry Andric NewMRTParent->addChild(NewMRTRegion);
6556b3f41edSDimitry Andric NewMRTRegion->setParent(NewMRTParent);
6566b3f41edSDimitry Andric RegionMap[Parent] = NewMRTParent;
6576b3f41edSDimitry Andric NewMRTRegion = NewMRTParent;
6586b3f41edSDimitry Andric Parent = Parent->getParent();
6596b3f41edSDimitry Andric }
6606b3f41edSDimitry Andric RegionMap[Parent]->addChild(NewMRTRegion);
6616b3f41edSDimitry Andric NewMRTRegion->setParent(RegionMap[Parent]);
6626b3f41edSDimitry Andric }
6636b3f41edSDimitry Andric
6646b3f41edSDimitry Andric // Add MBB to Region MRT
6656b3f41edSDimitry Andric RegionMap[Region]->addChild(NewMBB);
6666b3f41edSDimitry Andric NewMBB->setParent(RegionMap[Region]);
6676b3f41edSDimitry Andric RegionMap[Region]->setSucc(Region->getExit());
6686b3f41edSDimitry Andric }
6696b3f41edSDimitry Andric return Result;
6706b3f41edSDimitry Andric }
6716b3f41edSDimitry Andric
storeLiveOutReg(MachineBasicBlock * MBB,Register Reg,MachineInstr * DefInstr,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo)672b60736ecSDimitry Andric void LinearizedRegion::storeLiveOutReg(MachineBasicBlock *MBB, Register Reg,
6736b3f41edSDimitry Andric MachineInstr *DefInstr,
6746b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
6756b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
6766b3f41edSDimitry Andric PHILinearize &PHIInfo) {
677b60736ecSDimitry Andric if (Reg.isVirtual()) {
678eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI)
679eb11fae6SDimitry Andric << "\n");
6806b3f41edSDimitry Andric // If this is a source register to a PHI we are chaining, it
6816b3f41edSDimitry Andric // must be live out.
6826b3f41edSDimitry Andric if (PHIInfo.isSource(Reg)) {
683eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (PHI): " << printReg(Reg, TRI) << "\n");
6846b3f41edSDimitry Andric addLiveOut(Reg);
6856b3f41edSDimitry Andric } else {
6866b3f41edSDimitry Andric // If this is live out of the MBB
6876b3f41edSDimitry Andric for (auto &UI : MRI->use_operands(Reg)) {
6886b3f41edSDimitry Andric if (UI.getParent()->getParent() != MBB) {
689eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (MBB " << printMBBReference(*MBB)
690044eb2f6SDimitry Andric << "): " << printReg(Reg, TRI) << "\n");
6916b3f41edSDimitry Andric addLiveOut(Reg);
6926b3f41edSDimitry Andric } else {
6936b3f41edSDimitry Andric // If the use is in the same MBB we have to make sure
6946b3f41edSDimitry Andric // it is after the def, otherwise it is live out in a loop
6956b3f41edSDimitry Andric MachineInstr *UseInstr = UI.getParent();
6966b3f41edSDimitry Andric for (MachineBasicBlock::instr_iterator
6976b3f41edSDimitry Andric MII = UseInstr->getIterator(),
6986b3f41edSDimitry Andric MIE = UseInstr->getParent()->instr_end();
6996b3f41edSDimitry Andric MII != MIE; ++MII) {
7006b3f41edSDimitry Andric if ((&(*MII)) == DefInstr) {
701eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Loop): " << printReg(Reg, TRI)
7026b3f41edSDimitry Andric << "\n");
7036b3f41edSDimitry Andric addLiveOut(Reg);
7046b3f41edSDimitry Andric }
7056b3f41edSDimitry Andric }
7066b3f41edSDimitry Andric }
7076b3f41edSDimitry Andric }
7086b3f41edSDimitry Andric }
7096b3f41edSDimitry Andric }
7106b3f41edSDimitry Andric }
7116b3f41edSDimitry Andric
storeLiveOutRegRegion(RegionMRT * Region,Register Reg,MachineInstr * DefInstr,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo)712b60736ecSDimitry Andric void LinearizedRegion::storeLiveOutRegRegion(RegionMRT *Region, Register Reg,
7136b3f41edSDimitry Andric MachineInstr *DefInstr,
7146b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
7156b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
7166b3f41edSDimitry Andric PHILinearize &PHIInfo) {
717b60736ecSDimitry Andric if (Reg.isVirtual()) {
718eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Considering Register: " << printReg(Reg, TRI)
719eb11fae6SDimitry Andric << "\n");
7206b3f41edSDimitry Andric for (auto &UI : MRI->use_operands(Reg)) {
7216b3f41edSDimitry Andric if (!Region->contains(UI.getParent()->getParent())) {
722eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (Region " << (void *)Region
723044eb2f6SDimitry Andric << "): " << printReg(Reg, TRI) << "\n");
7246b3f41edSDimitry Andric addLiveOut(Reg);
7256b3f41edSDimitry Andric }
7266b3f41edSDimitry Andric }
7276b3f41edSDimitry Andric }
7286b3f41edSDimitry Andric }
7296b3f41edSDimitry Andric
storeLiveOuts(MachineBasicBlock * MBB,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo)7306b3f41edSDimitry Andric void LinearizedRegion::storeLiveOuts(MachineBasicBlock *MBB,
7316b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
7326b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
7336b3f41edSDimitry Andric PHILinearize &PHIInfo) {
734eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Begin (" << printMBBReference(*MBB)
735044eb2f6SDimitry Andric << ")-\n");
7366b3f41edSDimitry Andric for (auto &II : *MBB) {
7376b3f41edSDimitry Andric for (auto &RI : II.defs()) {
7386b3f41edSDimitry Andric storeLiveOutReg(MBB, RI.getReg(), RI.getParent(), MRI, TRI, PHIInfo);
7396b3f41edSDimitry Andric }
7406b3f41edSDimitry Andric for (auto &IRI : II.implicit_operands()) {
7416b3f41edSDimitry Andric if (IRI.isDef()) {
7426b3f41edSDimitry Andric storeLiveOutReg(MBB, IRI.getReg(), IRI.getParent(), MRI, TRI, PHIInfo);
7436b3f41edSDimitry Andric }
7446b3f41edSDimitry Andric }
7456b3f41edSDimitry Andric }
7466b3f41edSDimitry Andric
7476b3f41edSDimitry Andric // If we have a successor with a PHI, source coming from this MBB we have to
7486b3f41edSDimitry Andric // add the register as live out
749c0981da4SDimitry Andric for (MachineBasicBlock *Succ : MBB->successors()) {
750c0981da4SDimitry Andric for (auto &II : *Succ) {
7516b3f41edSDimitry Andric if (II.isPHI()) {
7526b3f41edSDimitry Andric MachineInstr &PHI = II;
7536b3f41edSDimitry Andric int numPreds = getPHINumInputs(PHI);
7546b3f41edSDimitry Andric for (int i = 0; i < numPreds; ++i) {
7556b3f41edSDimitry Andric if (getPHIPred(PHI, i) == MBB) {
7566b3f41edSDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i);
757eb11fae6SDimitry Andric LLVM_DEBUG(dbgs()
758eb11fae6SDimitry Andric << "Add LiveOut (PhiSource " << printMBBReference(*MBB)
759c0981da4SDimitry Andric << " -> " << printMBBReference(*Succ)
760044eb2f6SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n");
7616b3f41edSDimitry Andric addLiveOut(PHIReg);
7626b3f41edSDimitry Andric }
7636b3f41edSDimitry Andric }
7646b3f41edSDimitry Andric }
7656b3f41edSDimitry Andric }
7666b3f41edSDimitry Andric }
7676b3f41edSDimitry Andric
768eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "-Store Live Outs Endn-\n");
7696b3f41edSDimitry Andric }
7706b3f41edSDimitry Andric
storeMBBLiveOuts(MachineBasicBlock * MBB,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo,RegionMRT * TopRegion)7716b3f41edSDimitry Andric void LinearizedRegion::storeMBBLiveOuts(MachineBasicBlock *MBB,
7726b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
7736b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
7746b3f41edSDimitry Andric PHILinearize &PHIInfo,
7756b3f41edSDimitry Andric RegionMRT *TopRegion) {
7766b3f41edSDimitry Andric for (auto &II : *MBB) {
7776b3f41edSDimitry Andric for (auto &RI : II.defs()) {
7786b3f41edSDimitry Andric storeLiveOutRegRegion(TopRegion, RI.getReg(), RI.getParent(), MRI, TRI,
7796b3f41edSDimitry Andric PHIInfo);
7806b3f41edSDimitry Andric }
7816b3f41edSDimitry Andric for (auto &IRI : II.implicit_operands()) {
7826b3f41edSDimitry Andric if (IRI.isDef()) {
7836b3f41edSDimitry Andric storeLiveOutRegRegion(TopRegion, IRI.getReg(), IRI.getParent(), MRI,
7846b3f41edSDimitry Andric TRI, PHIInfo);
7856b3f41edSDimitry Andric }
7866b3f41edSDimitry Andric }
7876b3f41edSDimitry Andric }
7886b3f41edSDimitry Andric }
7896b3f41edSDimitry Andric
storeLiveOuts(RegionMRT * Region,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo,RegionMRT * CurrentTopRegion)7906b3f41edSDimitry Andric void LinearizedRegion::storeLiveOuts(RegionMRT *Region,
7916b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
7926b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
7936b3f41edSDimitry Andric PHILinearize &PHIInfo,
7946b3f41edSDimitry Andric RegionMRT *CurrentTopRegion) {
7956b3f41edSDimitry Andric MachineBasicBlock *Exit = Region->getSucc();
7966b3f41edSDimitry Andric
7976b3f41edSDimitry Andric RegionMRT *TopRegion =
7986b3f41edSDimitry Andric CurrentTopRegion == nullptr ? Region : CurrentTopRegion;
7996b3f41edSDimitry Andric
8006b3f41edSDimitry Andric // Check if exit is end of function, if so, no live outs.
8016b3f41edSDimitry Andric if (Exit == nullptr)
8026b3f41edSDimitry Andric return;
8036b3f41edSDimitry Andric
8046b3f41edSDimitry Andric auto Children = Region->getChildren();
805e3b55780SDimitry Andric for (auto *CI : *Children) {
8066b3f41edSDimitry Andric if (CI->isMBB()) {
8076b3f41edSDimitry Andric auto MBB = CI->getMBBMRT()->getMBB();
8086b3f41edSDimitry Andric storeMBBLiveOuts(MBB, MRI, TRI, PHIInfo, TopRegion);
8096b3f41edSDimitry Andric } else {
8106b3f41edSDimitry Andric LinearizedRegion *SubRegion = CI->getRegionMRT()->getLinearizedRegion();
8116b3f41edSDimitry Andric // We should be limited to only store registers that are live out from the
812c0981da4SDimitry Andric // linearized region
813e3b55780SDimitry Andric for (auto *MBBI : SubRegion->MBBs) {
8146b3f41edSDimitry Andric storeMBBLiveOuts(MBBI, MRI, TRI, PHIInfo, TopRegion);
8156b3f41edSDimitry Andric }
8166b3f41edSDimitry Andric }
8176b3f41edSDimitry Andric }
8186b3f41edSDimitry Andric
8196b3f41edSDimitry Andric if (CurrentTopRegion == nullptr) {
8206b3f41edSDimitry Andric auto Succ = Region->getSucc();
8216b3f41edSDimitry Andric for (auto &II : *Succ) {
8226b3f41edSDimitry Andric if (II.isPHI()) {
8236b3f41edSDimitry Andric MachineInstr &PHI = II;
8246b3f41edSDimitry Andric int numPreds = getPHINumInputs(PHI);
8256b3f41edSDimitry Andric for (int i = 0; i < numPreds; ++i) {
8266b3f41edSDimitry Andric if (Region->contains(getPHIPred(PHI, i))) {
8276b3f41edSDimitry Andric unsigned PHIReg = getPHISourceReg(PHI, i);
828eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add Region LiveOut (" << (void *)Region
829044eb2f6SDimitry Andric << "): " << printReg(PHIReg, TRI) << "\n");
8306b3f41edSDimitry Andric addLiveOut(PHIReg);
8316b3f41edSDimitry Andric }
8326b3f41edSDimitry Andric }
8336b3f41edSDimitry Andric }
8346b3f41edSDimitry Andric }
8356b3f41edSDimitry Andric }
8366b3f41edSDimitry Andric }
8376b3f41edSDimitry Andric
838044eb2f6SDimitry Andric #ifndef NDEBUG
print(raw_ostream & OS,const TargetRegisterInfo * TRI)8396b3f41edSDimitry Andric void LinearizedRegion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
8406b3f41edSDimitry Andric OS << "Linearized Region {";
8416b3f41edSDimitry Andric bool IsFirst = true;
842e3b55780SDimitry Andric for (auto *MBB : MBBs) {
8436b3f41edSDimitry Andric if (IsFirst) {
8446b3f41edSDimitry Andric IsFirst = false;
8456b3f41edSDimitry Andric } else {
8466b3f41edSDimitry Andric OS << " ,";
8476b3f41edSDimitry Andric }
8486b3f41edSDimitry Andric OS << MBB->getNumber();
8496b3f41edSDimitry Andric }
8506b3f41edSDimitry Andric OS << "} (" << Entry->getNumber() << ", "
8516b3f41edSDimitry Andric << (Exit == nullptr ? -1 : Exit->getNumber())
852044eb2f6SDimitry Andric << "): In:" << printReg(getBBSelectRegIn(), TRI)
853044eb2f6SDimitry Andric << " Out:" << printReg(getBBSelectRegOut(), TRI) << " {";
8546b3f41edSDimitry Andric for (auto &LI : LiveOuts) {
855044eb2f6SDimitry Andric OS << printReg(LI, TRI) << " ";
8566b3f41edSDimitry Andric }
8576b3f41edSDimitry Andric OS << "} \n";
8586b3f41edSDimitry Andric }
859044eb2f6SDimitry Andric #endif
8606b3f41edSDimitry Andric
getBBSelectRegIn()8616b3f41edSDimitry Andric unsigned LinearizedRegion::getBBSelectRegIn() {
8626b3f41edSDimitry Andric return getRegionMRT()->getBBSelectRegIn();
8636b3f41edSDimitry Andric }
8646b3f41edSDimitry Andric
getBBSelectRegOut()8656b3f41edSDimitry Andric unsigned LinearizedRegion::getBBSelectRegOut() {
8666b3f41edSDimitry Andric return getRegionMRT()->getBBSelectRegOut();
8676b3f41edSDimitry Andric }
8686b3f41edSDimitry Andric
setHasLoop(bool Value)8696b3f41edSDimitry Andric void LinearizedRegion::setHasLoop(bool Value) { HasLoop = Value; }
8706b3f41edSDimitry Andric
getHasLoop()8716b3f41edSDimitry Andric bool LinearizedRegion::getHasLoop() { return HasLoop; }
8726b3f41edSDimitry Andric
addLiveOut(unsigned VReg)8736b3f41edSDimitry Andric void LinearizedRegion::addLiveOut(unsigned VReg) { LiveOuts.insert(VReg); }
8746b3f41edSDimitry Andric
removeLiveOut(unsigned Reg)8756b3f41edSDimitry Andric void LinearizedRegion::removeLiveOut(unsigned Reg) {
8766b3f41edSDimitry Andric if (isLiveOut(Reg))
8776b3f41edSDimitry Andric LiveOuts.erase(Reg);
8786b3f41edSDimitry Andric }
8796b3f41edSDimitry Andric
replaceLiveOut(unsigned OldReg,unsigned NewReg)8806b3f41edSDimitry Andric void LinearizedRegion::replaceLiveOut(unsigned OldReg, unsigned NewReg) {
8816b3f41edSDimitry Andric if (isLiveOut(OldReg)) {
8826b3f41edSDimitry Andric removeLiveOut(OldReg);
8836b3f41edSDimitry Andric addLiveOut(NewReg);
8846b3f41edSDimitry Andric }
8856b3f41edSDimitry Andric }
8866b3f41edSDimitry Andric
replaceRegister(unsigned Register,class Register NewRegister,MachineRegisterInfo * MRI,bool ReplaceInside,bool ReplaceOutside,bool IncludeLoopPHI)887b60736ecSDimitry Andric void LinearizedRegion::replaceRegister(unsigned Register,
888b60736ecSDimitry Andric class Register NewRegister,
8896b3f41edSDimitry Andric MachineRegisterInfo *MRI,
8906b3f41edSDimitry Andric bool ReplaceInside, bool ReplaceOutside,
8916b3f41edSDimitry Andric bool IncludeLoopPHI) {
8926b3f41edSDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself");
8936b3f41edSDimitry Andric
894eb11fae6SDimitry Andric LLVM_DEBUG(
895c0981da4SDimitry Andric dbgs() << "Preparing to replace register (region): "
896044eb2f6SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo()) << " with "
897044eb2f6SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo()) << "\n");
8986b3f41edSDimitry Andric
8996b3f41edSDimitry Andric // If we are replacing outside, we also need to update the LiveOuts
9006b3f41edSDimitry Andric if (ReplaceOutside &&
9016b3f41edSDimitry Andric (isLiveOut(Register) || this->getParent()->isLiveOut(Register))) {
9026b3f41edSDimitry Andric LinearizedRegion *Current = this;
9036b3f41edSDimitry Andric while (Current != nullptr && Current->getEntry() != nullptr) {
904eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Region before register replace\n");
905eb11fae6SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo()));
9066b3f41edSDimitry Andric Current->replaceLiveOut(Register, NewRegister);
907eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Region after register replace\n");
908eb11fae6SDimitry Andric LLVM_DEBUG(Current->print(dbgs(), MRI->getTargetRegisterInfo()));
9096b3f41edSDimitry Andric Current = Current->getParent();
9106b3f41edSDimitry Andric }
9116b3f41edSDimitry Andric }
9126b3f41edSDimitry Andric
9136b3f41edSDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register),
9146b3f41edSDimitry Andric E = MRI->reg_end();
9156b3f41edSDimitry Andric I != E;) {
9166b3f41edSDimitry Andric MachineOperand &O = *I;
9176b3f41edSDimitry Andric ++I;
9186b3f41edSDimitry Andric
9196b3f41edSDimitry Andric // We don't rewrite defs.
9206b3f41edSDimitry Andric if (O.isDef())
9216b3f41edSDimitry Andric continue;
9226b3f41edSDimitry Andric
9236b3f41edSDimitry Andric bool IsInside = contains(O.getParent()->getParent());
9246b3f41edSDimitry Andric bool IsLoopPHI = IsInside && (O.getParent()->isPHI() &&
9256b3f41edSDimitry Andric O.getParent()->getParent() == getEntry());
9266b3f41edSDimitry Andric bool ShouldReplace = (IsInside && ReplaceInside) ||
9276b3f41edSDimitry Andric (!IsInside && ReplaceOutside) ||
9286b3f41edSDimitry Andric (IncludeLoopPHI && IsLoopPHI);
9296b3f41edSDimitry Andric if (ShouldReplace) {
9306b3f41edSDimitry Andric
931b60736ecSDimitry Andric if (NewRegister.isPhysical()) {
932eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: "
933044eb2f6SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo())
9346b3f41edSDimitry Andric << "\n");
9356b3f41edSDimitry Andric llvm_unreachable("Cannot substitute physical registers");
9366b3f41edSDimitry Andric } else {
937eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register (region): "
938044eb2f6SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo())
9396b3f41edSDimitry Andric << " with "
940044eb2f6SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo())
9416b3f41edSDimitry Andric << "\n");
9426b3f41edSDimitry Andric O.setReg(NewRegister);
9436b3f41edSDimitry Andric }
9446b3f41edSDimitry Andric }
9456b3f41edSDimitry Andric }
9466b3f41edSDimitry Andric }
9476b3f41edSDimitry Andric
replaceRegisterInsideRegion(unsigned Register,unsigned NewRegister,bool IncludeLoopPHIs,MachineRegisterInfo * MRI)9486b3f41edSDimitry Andric void LinearizedRegion::replaceRegisterInsideRegion(unsigned Register,
9496b3f41edSDimitry Andric unsigned NewRegister,
9506b3f41edSDimitry Andric bool IncludeLoopPHIs,
9516b3f41edSDimitry Andric MachineRegisterInfo *MRI) {
9526b3f41edSDimitry Andric replaceRegister(Register, NewRegister, MRI, true, false, IncludeLoopPHIs);
9536b3f41edSDimitry Andric }
9546b3f41edSDimitry Andric
replaceRegisterOutsideRegion(unsigned Register,unsigned NewRegister,bool IncludeLoopPHIs,MachineRegisterInfo * MRI)9556b3f41edSDimitry Andric void LinearizedRegion::replaceRegisterOutsideRegion(unsigned Register,
9566b3f41edSDimitry Andric unsigned NewRegister,
9576b3f41edSDimitry Andric bool IncludeLoopPHIs,
9586b3f41edSDimitry Andric MachineRegisterInfo *MRI) {
9596b3f41edSDimitry Andric replaceRegister(Register, NewRegister, MRI, false, true, IncludeLoopPHIs);
9606b3f41edSDimitry Andric }
9616b3f41edSDimitry Andric
getLiveOuts()9626b3f41edSDimitry Andric DenseSet<unsigned> *LinearizedRegion::getLiveOuts() { return &LiveOuts; }
9636b3f41edSDimitry Andric
setEntry(MachineBasicBlock * NewEntry)9646b3f41edSDimitry Andric void LinearizedRegion::setEntry(MachineBasicBlock *NewEntry) {
9656b3f41edSDimitry Andric Entry = NewEntry;
9666b3f41edSDimitry Andric }
9676b3f41edSDimitry Andric
getEntry()9686b3f41edSDimitry Andric MachineBasicBlock *LinearizedRegion::getEntry() { return Entry; }
9696b3f41edSDimitry Andric
setExit(MachineBasicBlock * NewExit)9706b3f41edSDimitry Andric void LinearizedRegion::setExit(MachineBasicBlock *NewExit) { Exit = NewExit; }
9716b3f41edSDimitry Andric
getExit()9726b3f41edSDimitry Andric MachineBasicBlock *LinearizedRegion::getExit() { return Exit; }
9736b3f41edSDimitry Andric
addMBB(MachineBasicBlock * MBB)9746b3f41edSDimitry Andric void LinearizedRegion::addMBB(MachineBasicBlock *MBB) { MBBs.insert(MBB); }
9756b3f41edSDimitry Andric
addMBBs(LinearizedRegion * InnerRegion)9766b3f41edSDimitry Andric void LinearizedRegion::addMBBs(LinearizedRegion *InnerRegion) {
977e3b55780SDimitry Andric for (auto *MBB : InnerRegion->MBBs) {
9786b3f41edSDimitry Andric addMBB(MBB);
9796b3f41edSDimitry Andric }
9806b3f41edSDimitry Andric }
9816b3f41edSDimitry Andric
contains(MachineBasicBlock * MBB)9826b3f41edSDimitry Andric bool LinearizedRegion::contains(MachineBasicBlock *MBB) {
983b60736ecSDimitry Andric return MBBs.contains(MBB);
9846b3f41edSDimitry Andric }
9856b3f41edSDimitry Andric
isLiveOut(unsigned Reg)9866b3f41edSDimitry Andric bool LinearizedRegion::isLiveOut(unsigned Reg) {
987b60736ecSDimitry Andric return LiveOuts.contains(Reg);
9886b3f41edSDimitry Andric }
9896b3f41edSDimitry Andric
hasNoDef(unsigned Reg,MachineRegisterInfo * MRI)9906b3f41edSDimitry Andric bool LinearizedRegion::hasNoDef(unsigned Reg, MachineRegisterInfo *MRI) {
9916b3f41edSDimitry Andric return MRI->def_begin(Reg) == MRI->def_end();
9926b3f41edSDimitry Andric }
9936b3f41edSDimitry Andric
9946b3f41edSDimitry Andric // After the code has been structurized, what was flagged as kills
9956b3f41edSDimitry Andric // before are no longer register kills.
removeFalseRegisterKills(MachineRegisterInfo * MRI)9966b3f41edSDimitry Andric void LinearizedRegion::removeFalseRegisterKills(MachineRegisterInfo *MRI) {
9976b3f41edSDimitry Andric const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
9981d5ae102SDimitry Andric (void)TRI; // It's used by LLVM_DEBUG.
9991d5ae102SDimitry Andric
1000e3b55780SDimitry Andric for (auto *MBBI : MBBs) {
10016b3f41edSDimitry Andric MachineBasicBlock *MBB = MBBI;
10026b3f41edSDimitry Andric for (auto &II : *MBB) {
10036b3f41edSDimitry Andric for (auto &RI : II.uses()) {
10046b3f41edSDimitry Andric if (RI.isReg()) {
10051d5ae102SDimitry Andric Register Reg = RI.getReg();
1006b60736ecSDimitry Andric if (Reg.isVirtual()) {
10076b3f41edSDimitry Andric if (hasNoDef(Reg, MRI))
10086b3f41edSDimitry Andric continue;
10096b3f41edSDimitry Andric if (!MRI->hasOneDef(Reg)) {
1010eb11fae6SDimitry Andric LLVM_DEBUG(this->getEntry()->getParent()->dump());
1011eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(Reg, TRI) << "\n");
10126b3f41edSDimitry Andric }
10136b3f41edSDimitry Andric
10146b3f41edSDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) {
1015eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Register "
1016044eb2f6SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo())
10176b3f41edSDimitry Andric << " has NO defs\n");
10186b3f41edSDimitry Andric } else if (!MRI->hasOneDef(Reg)) {
1019eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Register "
1020044eb2f6SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo())
10216b3f41edSDimitry Andric << " has multiple defs\n");
10226b3f41edSDimitry Andric }
10236b3f41edSDimitry Andric
10246b3f41edSDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions");
10256b3f41edSDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(Reg)));
10266b3f41edSDimitry Andric MachineOperand *UseOperand = &(RI);
10276b3f41edSDimitry Andric bool UseIsOutsideDefMBB = Def->getParent()->getParent() != MBB;
10286b3f41edSDimitry Andric if (UseIsOutsideDefMBB && UseOperand->isKill()) {
1029eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Removing kill flag on register: "
1030044eb2f6SDimitry Andric << printReg(Reg, TRI) << "\n");
10316b3f41edSDimitry Andric UseOperand->setIsKill(false);
10326b3f41edSDimitry Andric }
10336b3f41edSDimitry Andric }
10346b3f41edSDimitry Andric }
10356b3f41edSDimitry Andric }
10366b3f41edSDimitry Andric }
10376b3f41edSDimitry Andric }
10386b3f41edSDimitry Andric }
10396b3f41edSDimitry Andric
initLiveOut(RegionMRT * Region,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo)10406b3f41edSDimitry Andric void LinearizedRegion::initLiveOut(RegionMRT *Region,
10416b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
10426b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
10436b3f41edSDimitry Andric PHILinearize &PHIInfo) {
10446b3f41edSDimitry Andric storeLiveOuts(Region, MRI, TRI, PHIInfo);
10456b3f41edSDimitry Andric }
10466b3f41edSDimitry Andric
LinearizedRegion(MachineBasicBlock * MBB,const MachineRegisterInfo * MRI,const TargetRegisterInfo * TRI,PHILinearize & PHIInfo)10476b3f41edSDimitry Andric LinearizedRegion::LinearizedRegion(MachineBasicBlock *MBB,
10486b3f41edSDimitry Andric const MachineRegisterInfo *MRI,
10496b3f41edSDimitry Andric const TargetRegisterInfo *TRI,
10506b3f41edSDimitry Andric PHILinearize &PHIInfo) {
10516b3f41edSDimitry Andric setEntry(MBB);
10526b3f41edSDimitry Andric setExit(MBB);
10536b3f41edSDimitry Andric storeLiveOuts(MBB, MRI, TRI, PHIInfo);
10546b3f41edSDimitry Andric MBBs.insert(MBB);
10556b3f41edSDimitry Andric Parent = nullptr;
10566b3f41edSDimitry Andric }
10576b3f41edSDimitry Andric
LinearizedRegion()10586b3f41edSDimitry Andric LinearizedRegion::LinearizedRegion() {
10596b3f41edSDimitry Andric setEntry(nullptr);
10606b3f41edSDimitry Andric setExit(nullptr);
10616b3f41edSDimitry Andric Parent = nullptr;
10626b3f41edSDimitry Andric }
10636b3f41edSDimitry Andric
1064044eb2f6SDimitry Andric namespace {
10656b3f41edSDimitry Andric
10666b3f41edSDimitry Andric class AMDGPUMachineCFGStructurizer : public MachineFunctionPass {
10676b3f41edSDimitry Andric private:
10686b3f41edSDimitry Andric const MachineRegionInfo *Regions;
10696b3f41edSDimitry Andric const SIInstrInfo *TII;
10706b3f41edSDimitry Andric const TargetRegisterInfo *TRI;
10716b3f41edSDimitry Andric MachineRegisterInfo *MRI;
10726b3f41edSDimitry Andric PHILinearize PHIInfo;
10736b3f41edSDimitry Andric DenseMap<MachineBasicBlock *, MachineBasicBlock *> FallthroughMap;
1074044eb2f6SDimitry Andric RegionMRT *RMRT;
10756b3f41edSDimitry Andric
10766b3f41edSDimitry Andric void getPHIRegionIndices(RegionMRT *Region, MachineInstr &PHI,
10776b3f41edSDimitry Andric SmallVector<unsigned, 2> &RegionIndices);
10786b3f41edSDimitry Andric void getPHIRegionIndices(LinearizedRegion *Region, MachineInstr &PHI,
10796b3f41edSDimitry Andric SmallVector<unsigned, 2> &RegionIndices);
10806b3f41edSDimitry Andric void getPHINonRegionIndices(LinearizedRegion *Region, MachineInstr &PHI,
10816b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices);
10826b3f41edSDimitry Andric
10836b3f41edSDimitry Andric void storePHILinearizationInfoDest(
10846b3f41edSDimitry Andric unsigned LDestReg, MachineInstr &PHI,
10856b3f41edSDimitry Andric SmallVector<unsigned, 2> *RegionIndices = nullptr);
10866b3f41edSDimitry Andric
10876b3f41edSDimitry Andric unsigned storePHILinearizationInfo(MachineInstr &PHI,
10886b3f41edSDimitry Andric SmallVector<unsigned, 2> *RegionIndices);
10896b3f41edSDimitry Andric
10906b3f41edSDimitry Andric void extractKilledPHIs(MachineBasicBlock *MBB);
10916b3f41edSDimitry Andric
10926b3f41edSDimitry Andric bool shrinkPHI(MachineInstr &PHI, SmallVector<unsigned, 2> &PHIIndices,
10936b3f41edSDimitry Andric unsigned *ReplaceReg);
10946b3f41edSDimitry Andric
10956b3f41edSDimitry Andric bool shrinkPHI(MachineInstr &PHI, unsigned CombinedSourceReg,
10966b3f41edSDimitry Andric MachineBasicBlock *SourceMBB,
10976b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIIndices, unsigned *ReplaceReg);
10986b3f41edSDimitry Andric
10996b3f41edSDimitry Andric void replacePHI(MachineInstr &PHI, unsigned CombinedSourceReg,
11006b3f41edSDimitry Andric MachineBasicBlock *LastMerge,
11016b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices);
11026b3f41edSDimitry Andric void replaceEntryPHI(MachineInstr &PHI, unsigned CombinedSourceReg,
11036b3f41edSDimitry Andric MachineBasicBlock *IfMBB,
11046b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices);
11056b3f41edSDimitry Andric void replaceLiveOutRegs(MachineInstr &PHI,
11066b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices,
11076b3f41edSDimitry Andric unsigned CombinedSourceReg,
11086b3f41edSDimitry Andric LinearizedRegion *LRegion);
11096b3f41edSDimitry Andric void rewriteRegionExitPHI(RegionMRT *Region, MachineBasicBlock *LastMerge,
11106b3f41edSDimitry Andric MachineInstr &PHI, LinearizedRegion *LRegion);
11116b3f41edSDimitry Andric
11126b3f41edSDimitry Andric void rewriteRegionExitPHIs(RegionMRT *Region, MachineBasicBlock *LastMerge,
11136b3f41edSDimitry Andric LinearizedRegion *LRegion);
11146b3f41edSDimitry Andric void rewriteRegionEntryPHI(LinearizedRegion *Region, MachineBasicBlock *IfMBB,
11156b3f41edSDimitry Andric MachineInstr &PHI);
11166b3f41edSDimitry Andric void rewriteRegionEntryPHIs(LinearizedRegion *Region,
11176b3f41edSDimitry Andric MachineBasicBlock *IfMBB);
11186b3f41edSDimitry Andric
11196b3f41edSDimitry Andric bool regionIsSimpleIf(RegionMRT *Region);
11206b3f41edSDimitry Andric
11216b3f41edSDimitry Andric void transformSimpleIfRegion(RegionMRT *Region);
11226b3f41edSDimitry Andric
11236b3f41edSDimitry Andric void insertUnconditionalBranch(MachineBasicBlock *MBB,
11246b3f41edSDimitry Andric MachineBasicBlock *Dest,
11256b3f41edSDimitry Andric const DebugLoc &DL = DebugLoc());
11266b3f41edSDimitry Andric
11276b3f41edSDimitry Andric MachineBasicBlock *createLinearizedExitBlock(RegionMRT *Region);
11286b3f41edSDimitry Andric
11296b3f41edSDimitry Andric void insertMergePHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB,
11306b3f41edSDimitry Andric MachineBasicBlock *MergeBB, unsigned DestRegister,
11316b3f41edSDimitry Andric unsigned IfSourceRegister, unsigned CodeSourceRegister,
11326b3f41edSDimitry Andric bool IsUndefIfSource = false);
11336b3f41edSDimitry Andric
11346b3f41edSDimitry Andric MachineBasicBlock *createIfBlock(MachineBasicBlock *MergeBB,
11356b3f41edSDimitry Andric MachineBasicBlock *CodeBBStart,
11366b3f41edSDimitry Andric MachineBasicBlock *CodeBBEnd,
11376b3f41edSDimitry Andric MachineBasicBlock *SelectBB, unsigned IfReg,
11386b3f41edSDimitry Andric bool InheritPreds);
11396b3f41edSDimitry Andric
11406b3f41edSDimitry Andric void prunePHIInfo(MachineBasicBlock *MBB);
11416b3f41edSDimitry Andric void createEntryPHI(LinearizedRegion *CurrentRegion, unsigned DestReg);
11426b3f41edSDimitry Andric
11436b3f41edSDimitry Andric void createEntryPHIs(LinearizedRegion *CurrentRegion);
11446b3f41edSDimitry Andric void resolvePHIInfos(MachineBasicBlock *FunctionEntry);
11456b3f41edSDimitry Andric
1146b60736ecSDimitry Andric void replaceRegisterWith(unsigned Register, class Register NewRegister);
11476b3f41edSDimitry Andric
11486b3f41edSDimitry Andric MachineBasicBlock *createIfRegion(MachineBasicBlock *MergeBB,
11496b3f41edSDimitry Andric MachineBasicBlock *CodeBB,
11506b3f41edSDimitry Andric LinearizedRegion *LRegion,
11516b3f41edSDimitry Andric unsigned BBSelectRegIn,
11526b3f41edSDimitry Andric unsigned BBSelectRegOut);
11536b3f41edSDimitry Andric
11546b3f41edSDimitry Andric MachineBasicBlock *
11556b3f41edSDimitry Andric createIfRegion(MachineBasicBlock *MergeMBB, LinearizedRegion *InnerRegion,
11566b3f41edSDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB,
11576b3f41edSDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut);
11586b3f41edSDimitry Andric void ensureCondIsNotKilled(SmallVector<MachineOperand, 1> Cond);
11596b3f41edSDimitry Andric
11606b3f41edSDimitry Andric void rewriteCodeBBTerminator(MachineBasicBlock *CodeBB,
11616b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
11626b3f41edSDimitry Andric unsigned BBSelectReg);
11636b3f41edSDimitry Andric
11646b3f41edSDimitry Andric MachineInstr *getDefInstr(unsigned Reg);
11656b3f41edSDimitry Andric void insertChainedPHI(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB,
11666b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
11676b3f41edSDimitry Andric LinearizedRegion *InnerRegion, unsigned DestReg,
11686b3f41edSDimitry Andric unsigned SourceReg);
11696b3f41edSDimitry Andric bool containsDef(MachineBasicBlock *MBB, LinearizedRegion *InnerRegion,
11706b3f41edSDimitry Andric unsigned Register);
11716b3f41edSDimitry Andric void rewriteLiveOutRegs(MachineBasicBlock *IfBB, MachineBasicBlock *CodeBB,
11726b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
11736b3f41edSDimitry Andric LinearizedRegion *InnerRegion,
11746b3f41edSDimitry Andric LinearizedRegion *LRegion);
11756b3f41edSDimitry Andric
11766b3f41edSDimitry Andric void splitLoopPHI(MachineInstr &PHI, MachineBasicBlock *Entry,
11776b3f41edSDimitry Andric MachineBasicBlock *EntrySucc, LinearizedRegion *LRegion);
11786b3f41edSDimitry Andric void splitLoopPHIs(MachineBasicBlock *Entry, MachineBasicBlock *EntrySucc,
11796b3f41edSDimitry Andric LinearizedRegion *LRegion);
11806b3f41edSDimitry Andric
11816b3f41edSDimitry Andric MachineBasicBlock *splitExit(LinearizedRegion *LRegion);
11826b3f41edSDimitry Andric
11836b3f41edSDimitry Andric MachineBasicBlock *splitEntry(LinearizedRegion *LRegion);
11846b3f41edSDimitry Andric
11856b3f41edSDimitry Andric LinearizedRegion *initLinearizedRegion(RegionMRT *Region);
11866b3f41edSDimitry Andric
11876b3f41edSDimitry Andric bool structurizeComplexRegion(RegionMRT *Region);
11886b3f41edSDimitry Andric
11896b3f41edSDimitry Andric bool structurizeRegion(RegionMRT *Region);
11906b3f41edSDimitry Andric
11916b3f41edSDimitry Andric bool structurizeRegions(RegionMRT *Region, bool isTopRegion);
11926b3f41edSDimitry Andric
11936b3f41edSDimitry Andric public:
11946b3f41edSDimitry Andric static char ID;
11956b3f41edSDimitry Andric
AMDGPUMachineCFGStructurizer()1196044eb2f6SDimitry Andric AMDGPUMachineCFGStructurizer() : MachineFunctionPass(ID) {
1197044eb2f6SDimitry Andric initializeAMDGPUMachineCFGStructurizerPass(*PassRegistry::getPassRegistry());
1198044eb2f6SDimitry Andric }
1199044eb2f6SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const12006b3f41edSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
12016b3f41edSDimitry Andric AU.addRequired<MachineRegionInfoPass>();
12026b3f41edSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
12036b3f41edSDimitry Andric }
12046b3f41edSDimitry Andric
12056b3f41edSDimitry Andric void initFallthroughMap(MachineFunction &MF);
12066b3f41edSDimitry Andric
12076b3f41edSDimitry Andric void createLinearizedRegion(RegionMRT *Region, unsigned SelectOut);
12086b3f41edSDimitry Andric
12096b3f41edSDimitry Andric unsigned initializeSelectRegisters(MRT *MRT, unsigned ExistingExitReg,
12106b3f41edSDimitry Andric MachineRegisterInfo *MRI,
12116b3f41edSDimitry Andric const SIInstrInfo *TII);
12126b3f41edSDimitry Andric
setRegionMRT(RegionMRT * RegionTree)12136b3f41edSDimitry Andric void setRegionMRT(RegionMRT *RegionTree) { RMRT = RegionTree; }
12146b3f41edSDimitry Andric
getRegionMRT()12156b3f41edSDimitry Andric RegionMRT *getRegionMRT() { return RMRT; }
12166b3f41edSDimitry Andric
12176b3f41edSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
12186b3f41edSDimitry Andric };
1219044eb2f6SDimitry Andric
1220044eb2f6SDimitry Andric } // end anonymous namespace
12216b3f41edSDimitry Andric
12226b3f41edSDimitry Andric char AMDGPUMachineCFGStructurizer::ID = 0;
12236b3f41edSDimitry Andric
regionIsSimpleIf(RegionMRT * Region)12246b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::regionIsSimpleIf(RegionMRT *Region) {
12256b3f41edSDimitry Andric MachineBasicBlock *Entry = Region->getEntry();
12266b3f41edSDimitry Andric MachineBasicBlock *Succ = Region->getSucc();
12276b3f41edSDimitry Andric bool FoundBypass = false;
12286b3f41edSDimitry Andric bool FoundIf = false;
12296b3f41edSDimitry Andric
12306b3f41edSDimitry Andric if (Entry->succ_size() != 2) {
12316b3f41edSDimitry Andric return false;
12326b3f41edSDimitry Andric }
12336b3f41edSDimitry Andric
1234c0981da4SDimitry Andric for (MachineBasicBlock *Current : Entry->successors()) {
12356b3f41edSDimitry Andric if (Current == Succ) {
12366b3f41edSDimitry Andric FoundBypass = true;
12376b3f41edSDimitry Andric } else if ((Current->succ_size() == 1) &&
12386b3f41edSDimitry Andric *(Current->succ_begin()) == Succ) {
12396b3f41edSDimitry Andric FoundIf = true;
12406b3f41edSDimitry Andric }
12416b3f41edSDimitry Andric }
12426b3f41edSDimitry Andric
12436b3f41edSDimitry Andric return FoundIf && FoundBypass;
12446b3f41edSDimitry Andric }
12456b3f41edSDimitry Andric
transformSimpleIfRegion(RegionMRT * Region)12466b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::transformSimpleIfRegion(RegionMRT *Region) {
12476b3f41edSDimitry Andric MachineBasicBlock *Entry = Region->getEntry();
12486b3f41edSDimitry Andric MachineBasicBlock *Exit = Region->getExit();
12496b3f41edSDimitry Andric TII->convertNonUniformIfRegion(Entry, Exit);
12506b3f41edSDimitry Andric }
12516b3f41edSDimitry Andric
fixMBBTerminator(MachineBasicBlock * MBB)12526b3f41edSDimitry Andric static void fixMBBTerminator(MachineBasicBlock *MBB) {
12536b3f41edSDimitry Andric if (MBB->succ_size() == 1) {
12546b3f41edSDimitry Andric auto *Succ = *(MBB->succ_begin());
12556b3f41edSDimitry Andric for (auto &TI : MBB->terminators()) {
12566b3f41edSDimitry Andric for (auto &UI : TI.uses()) {
12576b3f41edSDimitry Andric if (UI.isMBB() && UI.getMBB() != Succ) {
12586b3f41edSDimitry Andric UI.setMBB(Succ);
12596b3f41edSDimitry Andric }
12606b3f41edSDimitry Andric }
12616b3f41edSDimitry Andric }
12626b3f41edSDimitry Andric }
12636b3f41edSDimitry Andric }
12646b3f41edSDimitry Andric
fixRegionTerminator(RegionMRT * Region)12656b3f41edSDimitry Andric static void fixRegionTerminator(RegionMRT *Region) {
12666b3f41edSDimitry Andric MachineBasicBlock *InternalSucc = nullptr;
12676b3f41edSDimitry Andric MachineBasicBlock *ExternalSucc = nullptr;
12686b3f41edSDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion();
12696b3f41edSDimitry Andric auto Exit = LRegion->getExit();
12706b3f41edSDimitry Andric
12716b3f41edSDimitry Andric SmallPtrSet<MachineBasicBlock *, 2> Successors;
1272c0981da4SDimitry Andric for (MachineBasicBlock *Succ : Exit->successors()) {
12736b3f41edSDimitry Andric if (LRegion->contains(Succ)) {
12746b3f41edSDimitry Andric // Do not allow re-assign
12756b3f41edSDimitry Andric assert(InternalSucc == nullptr);
12766b3f41edSDimitry Andric InternalSucc = Succ;
12776b3f41edSDimitry Andric } else {
12786b3f41edSDimitry Andric // Do not allow re-assign
12796b3f41edSDimitry Andric assert(ExternalSucc == nullptr);
12806b3f41edSDimitry Andric ExternalSucc = Succ;
12816b3f41edSDimitry Andric }
12826b3f41edSDimitry Andric }
12836b3f41edSDimitry Andric
12846b3f41edSDimitry Andric for (auto &TI : Exit->terminators()) {
12856b3f41edSDimitry Andric for (auto &UI : TI.uses()) {
12866b3f41edSDimitry Andric if (UI.isMBB()) {
12876b3f41edSDimitry Andric auto Target = UI.getMBB();
12886b3f41edSDimitry Andric if (Target != InternalSucc && Target != ExternalSucc) {
12896b3f41edSDimitry Andric UI.setMBB(ExternalSucc);
12906b3f41edSDimitry Andric }
12916b3f41edSDimitry Andric }
12926b3f41edSDimitry Andric }
12936b3f41edSDimitry Andric }
12946b3f41edSDimitry Andric }
12956b3f41edSDimitry Andric
1296145449b1SDimitry Andric // If a region is just a sequence of regions (and the exit
12976b3f41edSDimitry Andric // block in the case of the top level region), we can simply skip
12986b3f41edSDimitry Andric // linearizing it, because it is already linear
regionIsSequence(RegionMRT * Region)12996b3f41edSDimitry Andric bool regionIsSequence(RegionMRT *Region) {
13006b3f41edSDimitry Andric auto Children = Region->getChildren();
1301e3b55780SDimitry Andric for (auto *CI : *Children) {
13026b3f41edSDimitry Andric if (!CI->isRegion()) {
13036b3f41edSDimitry Andric if (CI->getMBBMRT()->getMBB()->succ_size() > 1) {
13046b3f41edSDimitry Andric return false;
13056b3f41edSDimitry Andric }
13066b3f41edSDimitry Andric }
13076b3f41edSDimitry Andric }
13086b3f41edSDimitry Andric return true;
13096b3f41edSDimitry Andric }
13106b3f41edSDimitry Andric
fixupRegionExits(RegionMRT * Region)13116b3f41edSDimitry Andric void fixupRegionExits(RegionMRT *Region) {
13126b3f41edSDimitry Andric auto Children = Region->getChildren();
1313e3b55780SDimitry Andric for (auto *CI : *Children) {
13146b3f41edSDimitry Andric if (!CI->isRegion()) {
13156b3f41edSDimitry Andric fixMBBTerminator(CI->getMBBMRT()->getMBB());
13166b3f41edSDimitry Andric } else {
13176b3f41edSDimitry Andric fixRegionTerminator(CI->getRegionMRT());
13186b3f41edSDimitry Andric }
13196b3f41edSDimitry Andric }
13206b3f41edSDimitry Andric }
13216b3f41edSDimitry Andric
getPHIRegionIndices(RegionMRT * Region,MachineInstr & PHI,SmallVector<unsigned,2> & PHIRegionIndices)13226b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices(
13236b3f41edSDimitry Andric RegionMRT *Region, MachineInstr &PHI,
13246b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) {
13256b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
13266b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
13276b3f41edSDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i);
13286b3f41edSDimitry Andric if (Region->contains(Pred)) {
13296b3f41edSDimitry Andric PHIRegionIndices.push_back(i);
13306b3f41edSDimitry Andric }
13316b3f41edSDimitry Andric }
13326b3f41edSDimitry Andric }
13336b3f41edSDimitry Andric
getPHIRegionIndices(LinearizedRegion * Region,MachineInstr & PHI,SmallVector<unsigned,2> & PHIRegionIndices)13346b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::getPHIRegionIndices(
13356b3f41edSDimitry Andric LinearizedRegion *Region, MachineInstr &PHI,
13366b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) {
13376b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
13386b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
13396b3f41edSDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i);
13406b3f41edSDimitry Andric if (Region->contains(Pred)) {
13416b3f41edSDimitry Andric PHIRegionIndices.push_back(i);
13426b3f41edSDimitry Andric }
13436b3f41edSDimitry Andric }
13446b3f41edSDimitry Andric }
13456b3f41edSDimitry Andric
getPHINonRegionIndices(LinearizedRegion * Region,MachineInstr & PHI,SmallVector<unsigned,2> & PHINonRegionIndices)13466b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::getPHINonRegionIndices(
13476b3f41edSDimitry Andric LinearizedRegion *Region, MachineInstr &PHI,
13486b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHINonRegionIndices) {
13496b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
13506b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
13516b3f41edSDimitry Andric MachineBasicBlock *Pred = getPHIPred(PHI, i);
13526b3f41edSDimitry Andric if (!Region->contains(Pred)) {
13536b3f41edSDimitry Andric PHINonRegionIndices.push_back(i);
13546b3f41edSDimitry Andric }
13556b3f41edSDimitry Andric }
13566b3f41edSDimitry Andric }
13576b3f41edSDimitry Andric
storePHILinearizationInfoDest(unsigned LDestReg,MachineInstr & PHI,SmallVector<unsigned,2> * RegionIndices)13586b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::storePHILinearizationInfoDest(
13596b3f41edSDimitry Andric unsigned LDestReg, MachineInstr &PHI,
13606b3f41edSDimitry Andric SmallVector<unsigned, 2> *RegionIndices) {
13616b3f41edSDimitry Andric if (RegionIndices) {
13626b3f41edSDimitry Andric for (auto i : *RegionIndices) {
13636b3f41edSDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i));
13646b3f41edSDimitry Andric }
13656b3f41edSDimitry Andric } else {
13666b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
13676b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
13686b3f41edSDimitry Andric PHIInfo.addSource(LDestReg, getPHISourceReg(PHI, i), getPHIPred(PHI, i));
13696b3f41edSDimitry Andric }
13706b3f41edSDimitry Andric }
13716b3f41edSDimitry Andric }
13726b3f41edSDimitry Andric
storePHILinearizationInfo(MachineInstr & PHI,SmallVector<unsigned,2> * RegionIndices)13736b3f41edSDimitry Andric unsigned AMDGPUMachineCFGStructurizer::storePHILinearizationInfo(
13746b3f41edSDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> *RegionIndices) {
13756b3f41edSDimitry Andric unsigned DestReg = getPHIDestReg(PHI);
13761d5ae102SDimitry Andric Register LinearizeDestReg =
13776b3f41edSDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(DestReg));
13786b3f41edSDimitry Andric PHIInfo.addDest(LinearizeDestReg, PHI.getDebugLoc());
13796b3f41edSDimitry Andric storePHILinearizationInfoDest(LinearizeDestReg, PHI, RegionIndices);
13806b3f41edSDimitry Andric return LinearizeDestReg;
13816b3f41edSDimitry Andric }
13826b3f41edSDimitry Andric
extractKilledPHIs(MachineBasicBlock * MBB)13836b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::extractKilledPHIs(MachineBasicBlock *MBB) {
13846b3f41edSDimitry Andric // We need to create a new chain for the killed phi, but there is no
13856b3f41edSDimitry Andric // need to do the renaming outside or inside the block.
13866b3f41edSDimitry Andric SmallPtrSet<MachineInstr *, 2> PHIs;
13876b3f41edSDimitry Andric for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(),
13886b3f41edSDimitry Andric E = MBB->instr_end();
13896b3f41edSDimitry Andric I != E; ++I) {
13906b3f41edSDimitry Andric MachineInstr &Instr = *I;
13916b3f41edSDimitry Andric if (Instr.isPHI()) {
13926b3f41edSDimitry Andric unsigned PHIDestReg = getPHIDestReg(Instr);
1393c0981da4SDimitry Andric LLVM_DEBUG(dbgs() << "Extracting killed phi:\n");
1394eb11fae6SDimitry Andric LLVM_DEBUG(Instr.dump());
13956b3f41edSDimitry Andric PHIs.insert(&Instr);
13966b3f41edSDimitry Andric PHIInfo.addDest(PHIDestReg, Instr.getDebugLoc());
13976b3f41edSDimitry Andric storePHILinearizationInfoDest(PHIDestReg, Instr);
13986b3f41edSDimitry Andric }
13996b3f41edSDimitry Andric }
14006b3f41edSDimitry Andric
1401e3b55780SDimitry Andric for (auto *PI : PHIs) {
14026b3f41edSDimitry Andric PI->eraseFromParent();
14036b3f41edSDimitry Andric }
14046b3f41edSDimitry Andric }
14056b3f41edSDimitry Andric
isPHIRegionIndex(SmallVector<unsigned,2> PHIRegionIndices,unsigned Index)14066b3f41edSDimitry Andric static bool isPHIRegionIndex(SmallVector<unsigned, 2> PHIRegionIndices,
14076b3f41edSDimitry Andric unsigned Index) {
1408344a3780SDimitry Andric return llvm::is_contained(PHIRegionIndices, Index);
14096b3f41edSDimitry Andric }
14106b3f41edSDimitry Andric
shrinkPHI(MachineInstr & PHI,SmallVector<unsigned,2> & PHIIndices,unsigned * ReplaceReg)14116b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI,
14126b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIIndices,
14136b3f41edSDimitry Andric unsigned *ReplaceReg) {
14146b3f41edSDimitry Andric return shrinkPHI(PHI, 0, nullptr, PHIIndices, ReplaceReg);
14156b3f41edSDimitry Andric }
14166b3f41edSDimitry Andric
shrinkPHI(MachineInstr & PHI,unsigned CombinedSourceReg,MachineBasicBlock * SourceMBB,SmallVector<unsigned,2> & PHIIndices,unsigned * ReplaceReg)14176b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI,
14186b3f41edSDimitry Andric unsigned CombinedSourceReg,
14196b3f41edSDimitry Andric MachineBasicBlock *SourceMBB,
14206b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIIndices,
14216b3f41edSDimitry Andric unsigned *ReplaceReg) {
1422eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Shrink PHI: ");
1423eb11fae6SDimitry Andric LLVM_DEBUG(PHI.dump());
1424eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " to " << printReg(getPHIDestReg(PHI), TRI)
1425eb11fae6SDimitry Andric << " = PHI(");
14266b3f41edSDimitry Andric
14276b3f41edSDimitry Andric bool Replaced = false;
14286b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
14296b3f41edSDimitry Andric int SingleExternalEntryIndex = -1;
14306b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
14316b3f41edSDimitry Andric if (!isPHIRegionIndex(PHIIndices, i)) {
14326b3f41edSDimitry Andric if (SingleExternalEntryIndex == -1) {
14336b3f41edSDimitry Andric // Single entry
14346b3f41edSDimitry Andric SingleExternalEntryIndex = i;
14356b3f41edSDimitry Andric } else {
14366b3f41edSDimitry Andric // Multiple entries
14376b3f41edSDimitry Andric SingleExternalEntryIndex = -2;
14386b3f41edSDimitry Andric }
14396b3f41edSDimitry Andric }
14406b3f41edSDimitry Andric }
14416b3f41edSDimitry Andric
14426b3f41edSDimitry Andric if (SingleExternalEntryIndex > -1) {
14436b3f41edSDimitry Andric *ReplaceReg = getPHISourceReg(PHI, SingleExternalEntryIndex);
14446b3f41edSDimitry Andric // We should not rewrite the code, we should only pick up the single value
14456b3f41edSDimitry Andric // that represents the shrunk PHI.
14466b3f41edSDimitry Andric Replaced = true;
14476b3f41edSDimitry Andric } else {
14486b3f41edSDimitry Andric MachineBasicBlock *MBB = PHI.getParent();
14496b3f41edSDimitry Andric MachineInstrBuilder MIB =
14506b3f41edSDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI),
14516b3f41edSDimitry Andric getPHIDestReg(PHI));
14526b3f41edSDimitry Andric if (SourceMBB) {
14536b3f41edSDimitry Andric MIB.addReg(CombinedSourceReg);
14546b3f41edSDimitry Andric MIB.addMBB(SourceMBB);
1455eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", "
1456044eb2f6SDimitry Andric << printMBBReference(*SourceMBB));
14576b3f41edSDimitry Andric }
14586b3f41edSDimitry Andric
14596b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
14606b3f41edSDimitry Andric if (isPHIRegionIndex(PHIIndices, i)) {
14616b3f41edSDimitry Andric continue;
14626b3f41edSDimitry Andric }
14636b3f41edSDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i);
14646b3f41edSDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i);
14656b3f41edSDimitry Andric MIB.addReg(SourceReg);
14666b3f41edSDimitry Andric MIB.addMBB(SourcePred);
1467eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", "
1468044eb2f6SDimitry Andric << printMBBReference(*SourcePred));
14696b3f41edSDimitry Andric }
1470eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ")\n");
14716b3f41edSDimitry Andric }
14726b3f41edSDimitry Andric PHI.eraseFromParent();
14736b3f41edSDimitry Andric return Replaced;
14746b3f41edSDimitry Andric }
14756b3f41edSDimitry Andric
replacePHI(MachineInstr & PHI,unsigned CombinedSourceReg,MachineBasicBlock * LastMerge,SmallVector<unsigned,2> & PHIRegionIndices)14766b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::replacePHI(
14776b3f41edSDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *LastMerge,
14786b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) {
1479eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Replace PHI: ");
1480eb11fae6SDimitry Andric LLVM_DEBUG(PHI.dump());
1481eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " with " << printReg(getPHIDestReg(PHI), TRI)
1482eb11fae6SDimitry Andric << " = PHI(");
14836b3f41edSDimitry Andric
14846b3f41edSDimitry Andric bool HasExternalEdge = false;
14856b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
14866b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
14876b3f41edSDimitry Andric if (!isPHIRegionIndex(PHIRegionIndices, i)) {
14886b3f41edSDimitry Andric HasExternalEdge = true;
14896b3f41edSDimitry Andric }
14906b3f41edSDimitry Andric }
14916b3f41edSDimitry Andric
14926b3f41edSDimitry Andric if (HasExternalEdge) {
14936b3f41edSDimitry Andric MachineBasicBlock *MBB = PHI.getParent();
14946b3f41edSDimitry Andric MachineInstrBuilder MIB =
14956b3f41edSDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI),
14966b3f41edSDimitry Andric getPHIDestReg(PHI));
14976b3f41edSDimitry Andric MIB.addReg(CombinedSourceReg);
14986b3f41edSDimitry Andric MIB.addMBB(LastMerge);
1499eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", "
1500044eb2f6SDimitry Andric << printMBBReference(*LastMerge));
15016b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
15026b3f41edSDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) {
15036b3f41edSDimitry Andric continue;
15046b3f41edSDimitry Andric }
15056b3f41edSDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i);
15066b3f41edSDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i);
15076b3f41edSDimitry Andric MIB.addReg(SourceReg);
15086b3f41edSDimitry Andric MIB.addMBB(SourcePred);
1509eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", "
1510044eb2f6SDimitry Andric << printMBBReference(*SourcePred));
15116b3f41edSDimitry Andric }
1512eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ")\n");
15136b3f41edSDimitry Andric } else {
15146b3f41edSDimitry Andric replaceRegisterWith(getPHIDestReg(PHI), CombinedSourceReg);
15156b3f41edSDimitry Andric }
15166b3f41edSDimitry Andric PHI.eraseFromParent();
15176b3f41edSDimitry Andric }
15186b3f41edSDimitry Andric
replaceEntryPHI(MachineInstr & PHI,unsigned CombinedSourceReg,MachineBasicBlock * IfMBB,SmallVector<unsigned,2> & PHIRegionIndices)15196b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::replaceEntryPHI(
15206b3f41edSDimitry Andric MachineInstr &PHI, unsigned CombinedSourceReg, MachineBasicBlock *IfMBB,
15216b3f41edSDimitry Andric SmallVector<unsigned, 2> &PHIRegionIndices) {
1522eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Replace entry PHI: ");
1523eb11fae6SDimitry Andric LLVM_DEBUG(PHI.dump());
1524eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " with ");
15256b3f41edSDimitry Andric
15266b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
15276b3f41edSDimitry Andric unsigned NumNonRegionInputs = NumInputs;
15286b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
15296b3f41edSDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) {
15306b3f41edSDimitry Andric NumNonRegionInputs--;
15316b3f41edSDimitry Andric }
15326b3f41edSDimitry Andric }
15336b3f41edSDimitry Andric
15346b3f41edSDimitry Andric if (NumNonRegionInputs == 0) {
15356b3f41edSDimitry Andric auto DestReg = getPHIDestReg(PHI);
15366b3f41edSDimitry Andric replaceRegisterWith(DestReg, CombinedSourceReg);
1537eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " register " << printReg(CombinedSourceReg, TRI)
1538eb11fae6SDimitry Andric << "\n");
15396b3f41edSDimitry Andric PHI.eraseFromParent();
15406b3f41edSDimitry Andric } else {
1541eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(getPHIDestReg(PHI), TRI) << " = PHI(");
15426b3f41edSDimitry Andric MachineBasicBlock *MBB = PHI.getParent();
15436b3f41edSDimitry Andric MachineInstrBuilder MIB =
15446b3f41edSDimitry Andric BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI),
15456b3f41edSDimitry Andric getPHIDestReg(PHI));
15466b3f41edSDimitry Andric MIB.addReg(CombinedSourceReg);
15476b3f41edSDimitry Andric MIB.addMBB(IfMBB);
1548eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CombinedSourceReg, TRI) << ", "
1549044eb2f6SDimitry Andric << printMBBReference(*IfMBB));
15506b3f41edSDimitry Andric unsigned NumInputs = getPHINumInputs(PHI);
15516b3f41edSDimitry Andric for (unsigned i = 0; i < NumInputs; ++i) {
15526b3f41edSDimitry Andric if (isPHIRegionIndex(PHIRegionIndices, i)) {
15536b3f41edSDimitry Andric continue;
15546b3f41edSDimitry Andric }
15556b3f41edSDimitry Andric unsigned SourceReg = getPHISourceReg(PHI, i);
15566b3f41edSDimitry Andric MachineBasicBlock *SourcePred = getPHIPred(PHI, i);
15576b3f41edSDimitry Andric MIB.addReg(SourceReg);
15586b3f41edSDimitry Andric MIB.addMBB(SourcePred);
1559eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", "
1560044eb2f6SDimitry Andric << printMBBReference(*SourcePred));
15616b3f41edSDimitry Andric }
1562eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ")\n");
15636b3f41edSDimitry Andric PHI.eraseFromParent();
15646b3f41edSDimitry Andric }
15656b3f41edSDimitry Andric }
15666b3f41edSDimitry Andric
replaceLiveOutRegs(MachineInstr & PHI,SmallVector<unsigned,2> & PHIRegionIndices,unsigned CombinedSourceReg,LinearizedRegion * LRegion)15676b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::replaceLiveOutRegs(
15686b3f41edSDimitry Andric MachineInstr &PHI, SmallVector<unsigned, 2> &PHIRegionIndices,
15696b3f41edSDimitry Andric unsigned CombinedSourceReg, LinearizedRegion *LRegion) {
15706b3f41edSDimitry Andric bool WasLiveOut = false;
15716b3f41edSDimitry Andric for (auto PII : PHIRegionIndices) {
15726b3f41edSDimitry Andric unsigned Reg = getPHISourceReg(PHI, PII);
15736b3f41edSDimitry Andric if (LRegion->isLiveOut(Reg)) {
15746b3f41edSDimitry Andric bool IsDead = true;
15756b3f41edSDimitry Andric
15766b3f41edSDimitry Andric // Check if register is live out of the basic block
15776b3f41edSDimitry Andric MachineBasicBlock *DefMBB = getDefInstr(Reg)->getParent();
1578c0981da4SDimitry Andric for (const MachineOperand &MO : MRI->use_operands(Reg))
1579c0981da4SDimitry Andric if (MO.getParent()->getParent() != DefMBB)
15806b3f41edSDimitry Andric IsDead = false;
15816b3f41edSDimitry Andric
1582eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Register " << printReg(Reg, TRI) << " is "
1583eb11fae6SDimitry Andric << (IsDead ? "dead" : "alive")
1584eb11fae6SDimitry Andric << " after PHI replace\n");
15856b3f41edSDimitry Andric if (IsDead) {
15866b3f41edSDimitry Andric LRegion->removeLiveOut(Reg);
15876b3f41edSDimitry Andric }
15886b3f41edSDimitry Andric WasLiveOut = true;
15896b3f41edSDimitry Andric }
15906b3f41edSDimitry Andric }
15916b3f41edSDimitry Andric
15926b3f41edSDimitry Andric if (WasLiveOut)
15936b3f41edSDimitry Andric LRegion->addLiveOut(CombinedSourceReg);
15946b3f41edSDimitry Andric }
15956b3f41edSDimitry Andric
rewriteRegionExitPHI(RegionMRT * Region,MachineBasicBlock * LastMerge,MachineInstr & PHI,LinearizedRegion * LRegion)15966b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHI(RegionMRT *Region,
15976b3f41edSDimitry Andric MachineBasicBlock *LastMerge,
15986b3f41edSDimitry Andric MachineInstr &PHI,
15996b3f41edSDimitry Andric LinearizedRegion *LRegion) {
16006b3f41edSDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices;
16016b3f41edSDimitry Andric getPHIRegionIndices(Region, PHI, PHIRegionIndices);
16026b3f41edSDimitry Andric unsigned LinearizedSourceReg =
16036b3f41edSDimitry Andric storePHILinearizationInfo(PHI, &PHIRegionIndices);
16046b3f41edSDimitry Andric
16056b3f41edSDimitry Andric replacePHI(PHI, LinearizedSourceReg, LastMerge, PHIRegionIndices);
16066b3f41edSDimitry Andric replaceLiveOutRegs(PHI, PHIRegionIndices, LinearizedSourceReg, LRegion);
16076b3f41edSDimitry Andric }
16086b3f41edSDimitry Andric
rewriteRegionEntryPHI(LinearizedRegion * Region,MachineBasicBlock * IfMBB,MachineInstr & PHI)16096b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHI(LinearizedRegion *Region,
16106b3f41edSDimitry Andric MachineBasicBlock *IfMBB,
16116b3f41edSDimitry Andric MachineInstr &PHI) {
16126b3f41edSDimitry Andric SmallVector<unsigned, 2> PHINonRegionIndices;
16136b3f41edSDimitry Andric getPHINonRegionIndices(Region, PHI, PHINonRegionIndices);
16146b3f41edSDimitry Andric unsigned LinearizedSourceReg =
16156b3f41edSDimitry Andric storePHILinearizationInfo(PHI, &PHINonRegionIndices);
16166b3f41edSDimitry Andric replaceEntryPHI(PHI, LinearizedSourceReg, IfMBB, PHINonRegionIndices);
16176b3f41edSDimitry Andric }
16186b3f41edSDimitry Andric
collectPHIs(MachineBasicBlock * MBB,SmallVector<MachineInstr *,2> & PHIs)16196b3f41edSDimitry Andric static void collectPHIs(MachineBasicBlock *MBB,
16206b3f41edSDimitry Andric SmallVector<MachineInstr *, 2> &PHIs) {
16216b3f41edSDimitry Andric for (auto &BBI : *MBB) {
16226b3f41edSDimitry Andric if (BBI.isPHI()) {
16236b3f41edSDimitry Andric PHIs.push_back(&BBI);
16246b3f41edSDimitry Andric }
16256b3f41edSDimitry Andric }
16266b3f41edSDimitry Andric }
16276b3f41edSDimitry Andric
rewriteRegionExitPHIs(RegionMRT * Region,MachineBasicBlock * LastMerge,LinearizedRegion * LRegion)16286b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionExitPHIs(RegionMRT *Region,
16296b3f41edSDimitry Andric MachineBasicBlock *LastMerge,
16306b3f41edSDimitry Andric LinearizedRegion *LRegion) {
16316b3f41edSDimitry Andric SmallVector<MachineInstr *, 2> PHIs;
16326b3f41edSDimitry Andric auto Exit = Region->getSucc();
16336b3f41edSDimitry Andric if (Exit == nullptr)
16346b3f41edSDimitry Andric return;
16356b3f41edSDimitry Andric
16366b3f41edSDimitry Andric collectPHIs(Exit, PHIs);
16376b3f41edSDimitry Andric
1638e3b55780SDimitry Andric for (auto *PHII : PHIs) {
16396b3f41edSDimitry Andric rewriteRegionExitPHI(Region, LastMerge, *PHII, LRegion);
16406b3f41edSDimitry Andric }
16416b3f41edSDimitry Andric }
16426b3f41edSDimitry Andric
rewriteRegionEntryPHIs(LinearizedRegion * Region,MachineBasicBlock * IfMBB)16436b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteRegionEntryPHIs(LinearizedRegion *Region,
16446b3f41edSDimitry Andric MachineBasicBlock *IfMBB) {
16456b3f41edSDimitry Andric SmallVector<MachineInstr *, 2> PHIs;
16466b3f41edSDimitry Andric auto Entry = Region->getEntry();
16476b3f41edSDimitry Andric
16486b3f41edSDimitry Andric collectPHIs(Entry, PHIs);
16496b3f41edSDimitry Andric
1650e3b55780SDimitry Andric for (auto *PHII : PHIs) {
16516b3f41edSDimitry Andric rewriteRegionEntryPHI(Region, IfMBB, *PHII);
16526b3f41edSDimitry Andric }
16536b3f41edSDimitry Andric }
16546b3f41edSDimitry Andric
insertUnconditionalBranch(MachineBasicBlock * MBB,MachineBasicBlock * Dest,const DebugLoc & DL)16556b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::insertUnconditionalBranch(MachineBasicBlock *MBB,
16566b3f41edSDimitry Andric MachineBasicBlock *Dest,
16576b3f41edSDimitry Andric const DebugLoc &DL) {
1658eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting unconditional branch: " << MBB->getNumber()
16596b3f41edSDimitry Andric << " -> " << Dest->getNumber() << "\n");
16606b3f41edSDimitry Andric MachineBasicBlock::instr_iterator Terminator = MBB->getFirstInstrTerminator();
16616b3f41edSDimitry Andric bool HasTerminator = Terminator != MBB->instr_end();
16626b3f41edSDimitry Andric if (HasTerminator) {
16636b3f41edSDimitry Andric TII->ReplaceTailWithBranchTo(Terminator, Dest);
16646b3f41edSDimitry Andric }
16656b3f41edSDimitry Andric if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(Dest)) {
16666b3f41edSDimitry Andric TII->insertUnconditionalBranch(*MBB, Dest, DL);
16676b3f41edSDimitry Andric }
16686b3f41edSDimitry Andric }
16696b3f41edSDimitry Andric
getSingleExitNode(MachineFunction & MF)16706b3f41edSDimitry Andric static MachineBasicBlock *getSingleExitNode(MachineFunction &MF) {
16716b3f41edSDimitry Andric MachineBasicBlock *result = nullptr;
16726b3f41edSDimitry Andric for (auto &MFI : MF) {
1673c0981da4SDimitry Andric if (MFI.succ_empty()) {
16746b3f41edSDimitry Andric if (result == nullptr) {
16756b3f41edSDimitry Andric result = &MFI;
16766b3f41edSDimitry Andric } else {
16776b3f41edSDimitry Andric return nullptr;
16786b3f41edSDimitry Andric }
16796b3f41edSDimitry Andric }
16806b3f41edSDimitry Andric }
16816b3f41edSDimitry Andric
16826b3f41edSDimitry Andric return result;
16836b3f41edSDimitry Andric }
16846b3f41edSDimitry Andric
hasOneExitNode(MachineFunction & MF)16856b3f41edSDimitry Andric static bool hasOneExitNode(MachineFunction &MF) {
16866b3f41edSDimitry Andric return getSingleExitNode(MF) != nullptr;
16876b3f41edSDimitry Andric }
16886b3f41edSDimitry Andric
16896b3f41edSDimitry Andric MachineBasicBlock *
createLinearizedExitBlock(RegionMRT * Region)16906b3f41edSDimitry Andric AMDGPUMachineCFGStructurizer::createLinearizedExitBlock(RegionMRT *Region) {
16916b3f41edSDimitry Andric auto Exit = Region->getSucc();
16926b3f41edSDimitry Andric
16936b3f41edSDimitry Andric // If the exit is the end of the function, we just use the existing
16946b3f41edSDimitry Andric MachineFunction *MF = Region->getEntry()->getParent();
16956b3f41edSDimitry Andric if (Exit == nullptr && hasOneExitNode(*MF)) {
16966b3f41edSDimitry Andric return &(*(--(Region->getEntry()->getParent()->end())));
16976b3f41edSDimitry Andric }
16986b3f41edSDimitry Andric
16996b3f41edSDimitry Andric MachineBasicBlock *LastMerge = MF->CreateMachineBasicBlock();
17006b3f41edSDimitry Andric if (Exit == nullptr) {
17016b3f41edSDimitry Andric MachineFunction::iterator ExitIter = MF->end();
17026b3f41edSDimitry Andric MF->insert(ExitIter, LastMerge);
17036b3f41edSDimitry Andric } else {
17046b3f41edSDimitry Andric MachineFunction::iterator ExitIter = Exit->getIterator();
17056b3f41edSDimitry Andric MF->insert(ExitIter, LastMerge);
17066b3f41edSDimitry Andric LastMerge->addSuccessor(Exit);
17076b3f41edSDimitry Andric insertUnconditionalBranch(LastMerge, Exit);
1708eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Created exit block: " << LastMerge->getNumber()
1709eb11fae6SDimitry Andric << "\n");
17106b3f41edSDimitry Andric }
17116b3f41edSDimitry Andric return LastMerge;
17126b3f41edSDimitry Andric }
17136b3f41edSDimitry Andric
insertMergePHI(MachineBasicBlock * IfBB,MachineBasicBlock * CodeBB,MachineBasicBlock * MergeBB,unsigned DestRegister,unsigned IfSourceRegister,unsigned CodeSourceRegister,bool IsUndefIfSource)17146b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::insertMergePHI(MachineBasicBlock *IfBB,
17156b3f41edSDimitry Andric MachineBasicBlock *CodeBB,
17166b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
17176b3f41edSDimitry Andric unsigned DestRegister,
17186b3f41edSDimitry Andric unsigned IfSourceRegister,
17196b3f41edSDimitry Andric unsigned CodeSourceRegister,
17206b3f41edSDimitry Andric bool IsUndefIfSource) {
17216b3f41edSDimitry Andric // If this is the function exit block, we don't need a phi.
17224df029ccSDimitry Andric if (MergeBB->succ_empty()) {
17236b3f41edSDimitry Andric return;
17246b3f41edSDimitry Andric }
1725eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Merge PHI (" << printMBBReference(*MergeBB)
1726044eb2f6SDimitry Andric << "): " << printReg(DestRegister, TRI) << " = PHI("
1727044eb2f6SDimitry Andric << printReg(IfSourceRegister, TRI) << ", "
1728eb11fae6SDimitry Andric << printMBBReference(*IfBB)
1729eb11fae6SDimitry Andric << printReg(CodeSourceRegister, TRI) << ", "
1730eb11fae6SDimitry Andric << printMBBReference(*CodeBB) << ")\n");
17316b3f41edSDimitry Andric const DebugLoc &DL = MergeBB->findDebugLoc(MergeBB->begin());
17326b3f41edSDimitry Andric MachineInstrBuilder MIB = BuildMI(*MergeBB, MergeBB->instr_begin(), DL,
17336b3f41edSDimitry Andric TII->get(TargetOpcode::PHI), DestRegister);
17346b3f41edSDimitry Andric if (IsUndefIfSource && false) {
17356b3f41edSDimitry Andric MIB.addReg(IfSourceRegister, RegState::Undef);
17366b3f41edSDimitry Andric } else {
17376b3f41edSDimitry Andric MIB.addReg(IfSourceRegister);
17386b3f41edSDimitry Andric }
17396b3f41edSDimitry Andric MIB.addMBB(IfBB);
17406b3f41edSDimitry Andric MIB.addReg(CodeSourceRegister);
17416b3f41edSDimitry Andric MIB.addMBB(CodeBB);
17426b3f41edSDimitry Andric }
17436b3f41edSDimitry Andric
removeExternalCFGSuccessors(MachineBasicBlock * MBB)17446b3f41edSDimitry Andric static void removeExternalCFGSuccessors(MachineBasicBlock *MBB) {
17456b3f41edSDimitry Andric for (MachineBasicBlock::succ_iterator PI = MBB->succ_begin(),
17466b3f41edSDimitry Andric E = MBB->succ_end();
17476b3f41edSDimitry Andric PI != E; ++PI) {
17486b3f41edSDimitry Andric if ((*PI) != MBB) {
17496b3f41edSDimitry Andric (MBB)->removeSuccessor(*PI);
17506b3f41edSDimitry Andric }
17516b3f41edSDimitry Andric }
17526b3f41edSDimitry Andric }
17536b3f41edSDimitry Andric
removeExternalCFGEdges(MachineBasicBlock * StartMBB,MachineBasicBlock * EndMBB)17546b3f41edSDimitry Andric static void removeExternalCFGEdges(MachineBasicBlock *StartMBB,
17556b3f41edSDimitry Andric MachineBasicBlock *EndMBB) {
17566b3f41edSDimitry Andric
1757c0981da4SDimitry Andric // We have to check against the StartMBB successor because a
17586b3f41edSDimitry Andric // structurized region with a loop will have the entry block split,
17596b3f41edSDimitry Andric // and the backedge will go to the entry successor.
17606b3f41edSDimitry Andric DenseSet<std::pair<MachineBasicBlock *, MachineBasicBlock *>> Succs;
17616b3f41edSDimitry Andric unsigned SuccSize = StartMBB->succ_size();
17626b3f41edSDimitry Andric if (SuccSize > 0) {
17636b3f41edSDimitry Andric MachineBasicBlock *StartMBBSucc = *(StartMBB->succ_begin());
1764c0981da4SDimitry Andric for (MachineBasicBlock *Succ : EndMBB->successors()) {
17656b3f41edSDimitry Andric // Either we have a back-edge to the entry block, or a back-edge to the
17669df3605dSDimitry Andric // successor of the entry block since the block may be split.
1767c0981da4SDimitry Andric if (Succ != StartMBB &&
1768c0981da4SDimitry Andric !(Succ == StartMBBSucc && StartMBB != EndMBB && SuccSize == 1)) {
17696b3f41edSDimitry Andric Succs.insert(
1770c0981da4SDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *>(EndMBB, Succ));
17716b3f41edSDimitry Andric }
17726b3f41edSDimitry Andric }
17736b3f41edSDimitry Andric }
17746b3f41edSDimitry Andric
1775c0981da4SDimitry Andric for (MachineBasicBlock *Pred : StartMBB->predecessors())
1776c0981da4SDimitry Andric if (Pred != EndMBB)
1777e3b55780SDimitry Andric Succs.insert(std::pair(Pred, StartMBB));
17786b3f41edSDimitry Andric
17796b3f41edSDimitry Andric for (auto SI : Succs) {
17806b3f41edSDimitry Andric std::pair<MachineBasicBlock *, MachineBasicBlock *> Edge = SI;
1781eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Removing edge: " << printMBBReference(*Edge.first)
1782044eb2f6SDimitry Andric << " -> " << printMBBReference(*Edge.second) << "\n");
17836b3f41edSDimitry Andric Edge.first->removeSuccessor(Edge.second);
17846b3f41edSDimitry Andric }
17856b3f41edSDimitry Andric }
17866b3f41edSDimitry Andric
createIfBlock(MachineBasicBlock * MergeBB,MachineBasicBlock * CodeBBStart,MachineBasicBlock * CodeBBEnd,MachineBasicBlock * SelectBB,unsigned IfReg,bool InheritPreds)17876b3f41edSDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfBlock(
17886b3f41edSDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBBStart,
17896b3f41edSDimitry Andric MachineBasicBlock *CodeBBEnd, MachineBasicBlock *SelectBB, unsigned IfReg,
17906b3f41edSDimitry Andric bool InheritPreds) {
17916b3f41edSDimitry Andric MachineFunction *MF = MergeBB->getParent();
17926b3f41edSDimitry Andric MachineBasicBlock *IfBB = MF->CreateMachineBasicBlock();
17936b3f41edSDimitry Andric
17946b3f41edSDimitry Andric if (InheritPreds) {
1795c0981da4SDimitry Andric for (MachineBasicBlock *Pred : CodeBBStart->predecessors())
1796c0981da4SDimitry Andric if (Pred != CodeBBEnd)
17976b3f41edSDimitry Andric Pred->addSuccessor(IfBB);
17986b3f41edSDimitry Andric }
17996b3f41edSDimitry Andric
18006b3f41edSDimitry Andric removeExternalCFGEdges(CodeBBStart, CodeBBEnd);
18016b3f41edSDimitry Andric
18026b3f41edSDimitry Andric auto CodeBBStartI = CodeBBStart->getIterator();
18036b3f41edSDimitry Andric auto CodeBBEndI = CodeBBEnd->getIterator();
18046b3f41edSDimitry Andric auto MergeIter = MergeBB->getIterator();
18056b3f41edSDimitry Andric MF->insert(MergeIter, IfBB);
18066b3f41edSDimitry Andric MF->splice(MergeIter, CodeBBStartI, ++CodeBBEndI);
18076b3f41edSDimitry Andric IfBB->addSuccessor(MergeBB);
18086b3f41edSDimitry Andric IfBB->addSuccessor(CodeBBStart);
18096b3f41edSDimitry Andric
1810eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Created If block: " << IfBB->getNumber() << "\n");
18119df3605dSDimitry Andric // Ensure that the MergeBB is a successor of the CodeEndBB.
18126b3f41edSDimitry Andric if (!CodeBBEnd->isSuccessor(MergeBB))
18136b3f41edSDimitry Andric CodeBBEnd->addSuccessor(MergeBB);
18146b3f41edSDimitry Andric
1815eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Moved " << printMBBReference(*CodeBBStart)
1816eb11fae6SDimitry Andric << " through " << printMBBReference(*CodeBBEnd) << "\n");
18176b3f41edSDimitry Andric
18186b3f41edSDimitry Andric // If we have a single predecessor we can find a reasonable debug location
18196b3f41edSDimitry Andric MachineBasicBlock *SinglePred =
18206b3f41edSDimitry Andric CodeBBStart->pred_size() == 1 ? *(CodeBBStart->pred_begin()) : nullptr;
18216b3f41edSDimitry Andric const DebugLoc &DL = SinglePred
18226b3f41edSDimitry Andric ? SinglePred->findDebugLoc(SinglePred->getFirstTerminator())
18236b3f41edSDimitry Andric : DebugLoc();
18246b3f41edSDimitry Andric
1825b60736ecSDimitry Andric Register Reg =
18266b3f41edSDimitry Andric TII->insertEQ(IfBB, IfBB->begin(), DL, IfReg,
18276b3f41edSDimitry Andric SelectBB->getNumber() /* CodeBBStart->getNumber() */);
18286b3f41edSDimitry Andric if (&(*(IfBB->getParent()->begin())) == IfBB) {
18296b3f41edSDimitry Andric TII->materializeImmediate(*IfBB, IfBB->begin(), DL, IfReg,
18306b3f41edSDimitry Andric CodeBBStart->getNumber());
18316b3f41edSDimitry Andric }
18326b3f41edSDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true);
18336b3f41edSDimitry Andric ArrayRef<MachineOperand> Cond(RegOp);
18346b3f41edSDimitry Andric TII->insertBranch(*IfBB, MergeBB, CodeBBStart, Cond, DL);
18356b3f41edSDimitry Andric
18366b3f41edSDimitry Andric return IfBB;
18376b3f41edSDimitry Andric }
18386b3f41edSDimitry Andric
ensureCondIsNotKilled(SmallVector<MachineOperand,1> Cond)18396b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::ensureCondIsNotKilled(
18406b3f41edSDimitry Andric SmallVector<MachineOperand, 1> Cond) {
18416b3f41edSDimitry Andric if (Cond.size() != 1)
18426b3f41edSDimitry Andric return;
18436b3f41edSDimitry Andric if (!Cond[0].isReg())
18446b3f41edSDimitry Andric return;
18456b3f41edSDimitry Andric
18461d5ae102SDimitry Andric Register CondReg = Cond[0].getReg();
1847c0981da4SDimitry Andric for (MachineOperand &MO : MRI->use_operands(CondReg))
1848c0981da4SDimitry Andric MO.setIsKill(false);
18496b3f41edSDimitry Andric }
18506b3f41edSDimitry Andric
rewriteCodeBBTerminator(MachineBasicBlock * CodeBB,MachineBasicBlock * MergeBB,unsigned BBSelectReg)18516b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteCodeBBTerminator(MachineBasicBlock *CodeBB,
18526b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
18536b3f41edSDimitry Andric unsigned BBSelectReg) {
18546b3f41edSDimitry Andric MachineBasicBlock *TrueBB = nullptr;
18556b3f41edSDimitry Andric MachineBasicBlock *FalseBB = nullptr;
18566b3f41edSDimitry Andric SmallVector<MachineOperand, 1> Cond;
18576b3f41edSDimitry Andric MachineBasicBlock *FallthroughBB = FallthroughMap[CodeBB];
18586b3f41edSDimitry Andric TII->analyzeBranch(*CodeBB, TrueBB, FalseBB, Cond);
18596b3f41edSDimitry Andric
18606b3f41edSDimitry Andric const DebugLoc &DL = CodeBB->findDebugLoc(CodeBB->getFirstTerminator());
18616b3f41edSDimitry Andric
18626b3f41edSDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr && FallthroughBB == nullptr) {
18636b3f41edSDimitry Andric // This is an exit block, hence no successors. We will assign the
18646b3f41edSDimitry Andric // bb select register to the entry block.
18656b3f41edSDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL,
18666b3f41edSDimitry Andric BBSelectReg,
18676b3f41edSDimitry Andric CodeBB->getParent()->begin()->getNumber());
18686b3f41edSDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL);
18696b3f41edSDimitry Andric return;
18706b3f41edSDimitry Andric }
18716b3f41edSDimitry Andric
18726b3f41edSDimitry Andric if (FalseBB == nullptr && TrueBB == nullptr) {
18736b3f41edSDimitry Andric TrueBB = FallthroughBB;
18746b3f41edSDimitry Andric } else if (TrueBB != nullptr) {
18756b3f41edSDimitry Andric FalseBB =
18766b3f41edSDimitry Andric (FallthroughBB && (FallthroughBB != TrueBB)) ? FallthroughBB : FalseBB;
18776b3f41edSDimitry Andric }
18786b3f41edSDimitry Andric
18796b3f41edSDimitry Andric if ((TrueBB != nullptr && FalseBB == nullptr) || (TrueBB == FalseBB)) {
18806b3f41edSDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL,
18816b3f41edSDimitry Andric BBSelectReg, TrueBB->getNumber());
18826b3f41edSDimitry Andric } else {
18836b3f41edSDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectReg);
18841d5ae102SDimitry Andric Register TrueBBReg = MRI->createVirtualRegister(RegClass);
18851d5ae102SDimitry Andric Register FalseBBReg = MRI->createVirtualRegister(RegClass);
18866b3f41edSDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL,
18876b3f41edSDimitry Andric TrueBBReg, TrueBB->getNumber());
18886b3f41edSDimitry Andric TII->materializeImmediate(*CodeBB, CodeBB->getFirstTerminator(), DL,
18896b3f41edSDimitry Andric FalseBBReg, FalseBB->getNumber());
18906b3f41edSDimitry Andric ensureCondIsNotKilled(Cond);
18916b3f41edSDimitry Andric TII->insertVectorSelect(*CodeBB, CodeBB->getFirstTerminator(), DL,
18926b3f41edSDimitry Andric BBSelectReg, Cond, TrueBBReg, FalseBBReg);
18936b3f41edSDimitry Andric }
18946b3f41edSDimitry Andric
18956b3f41edSDimitry Andric insertUnconditionalBranch(CodeBB, MergeBB, DL);
18966b3f41edSDimitry Andric }
18976b3f41edSDimitry Andric
getDefInstr(unsigned Reg)18986b3f41edSDimitry Andric MachineInstr *AMDGPUMachineCFGStructurizer::getDefInstr(unsigned Reg) {
18996b3f41edSDimitry Andric if (MRI->def_begin(Reg) == MRI->def_end()) {
1900eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Register "
1901eb11fae6SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo())
19026b3f41edSDimitry Andric << " has NO defs\n");
19036b3f41edSDimitry Andric } else if (!MRI->hasOneDef(Reg)) {
1904eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Register "
1905eb11fae6SDimitry Andric << printReg(Reg, MRI->getTargetRegisterInfo())
19066b3f41edSDimitry Andric << " has multiple defs\n");
1907eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS BEGIN:\n");
19086b3f41edSDimitry Andric for (auto DI = MRI->def_begin(Reg), DE = MRI->def_end(); DI != DE; ++DI) {
1909eb11fae6SDimitry Andric LLVM_DEBUG(DI->getParent()->dump());
19106b3f41edSDimitry Andric }
1911eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "DEFS END\n");
19126b3f41edSDimitry Andric }
19136b3f41edSDimitry Andric
19146b3f41edSDimitry Andric assert(MRI->hasOneDef(Reg) && "Register has multiple definitions");
19156b3f41edSDimitry Andric return (*(MRI->def_begin(Reg))).getParent();
19166b3f41edSDimitry Andric }
19176b3f41edSDimitry Andric
insertChainedPHI(MachineBasicBlock * IfBB,MachineBasicBlock * CodeBB,MachineBasicBlock * MergeBB,LinearizedRegion * InnerRegion,unsigned DestReg,unsigned SourceReg)19186b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::insertChainedPHI(MachineBasicBlock *IfBB,
19196b3f41edSDimitry Andric MachineBasicBlock *CodeBB,
19206b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
19216b3f41edSDimitry Andric LinearizedRegion *InnerRegion,
19226b3f41edSDimitry Andric unsigned DestReg,
19236b3f41edSDimitry Andric unsigned SourceReg) {
19246b3f41edSDimitry Andric // In this function we know we are part of a chain already, so we need
19256b3f41edSDimitry Andric // to add the registers to the existing chain, and rename the register
19266b3f41edSDimitry Andric // inside the region.
19276b3f41edSDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit();
19286b3f41edSDimitry Andric MachineInstr *DefInstr = getDefInstr(SourceReg);
19296b3f41edSDimitry Andric if (DefInstr->isPHI() && DefInstr->getParent() == CodeBB && IsSingleBB) {
19306b3f41edSDimitry Andric // Handle the case where the def is a PHI-def inside a basic
19316b3f41edSDimitry Andric // block, then we only need to do renaming. Special care needs to
19326b3f41edSDimitry Andric // be taken if the PHI-def is part of an existing chain, or if a
19336b3f41edSDimitry Andric // new one needs to be created.
19346b3f41edSDimitry Andric InnerRegion->replaceRegisterInsideRegion(SourceReg, DestReg, true, MRI);
19356b3f41edSDimitry Andric
19366b3f41edSDimitry Andric // We collect all PHI Information, and if we are at the region entry,
19376b3f41edSDimitry Andric // all PHIs will be removed, and then re-introduced if needed.
19386b3f41edSDimitry Andric storePHILinearizationInfoDest(DestReg, *DefInstr);
19396b3f41edSDimitry Andric // We have picked up all the information we need now and can remove
19406b3f41edSDimitry Andric // the PHI
19416b3f41edSDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB);
19426b3f41edSDimitry Andric DefInstr->eraseFromParent();
19436b3f41edSDimitry Andric } else {
19446b3f41edSDimitry Andric // If this is not a phi-def, or it is a phi-def but from a linearized region
19456b3f41edSDimitry Andric if (IsSingleBB && DefInstr->getParent() == InnerRegion->getEntry()) {
19466b3f41edSDimitry Andric // If this is a single BB and the definition is in this block we
19476b3f41edSDimitry Andric // need to replace any uses outside the region.
19486b3f41edSDimitry Andric InnerRegion->replaceRegisterOutsideRegion(SourceReg, DestReg, false, MRI);
19496b3f41edSDimitry Andric }
19506b3f41edSDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(DestReg);
19511d5ae102SDimitry Andric Register NextDestReg = MRI->createVirtualRegister(RegClass);
19526b3f41edSDimitry Andric bool IsLastDef = PHIInfo.getNumSources(DestReg) == 1;
1953eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Chained PHI\n");
19546b3f41edSDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, DestReg, NextDestReg,
19556b3f41edSDimitry Andric SourceReg, IsLastDef);
19566b3f41edSDimitry Andric
19576b3f41edSDimitry Andric PHIInfo.removeSource(DestReg, SourceReg, CodeBB);
19586b3f41edSDimitry Andric if (IsLastDef) {
19596b3f41edSDimitry Andric const DebugLoc &DL = IfBB->findDebugLoc(IfBB->getFirstTerminator());
19606b3f41edSDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DL,
19616b3f41edSDimitry Andric NextDestReg, 0);
19626b3f41edSDimitry Andric PHIInfo.deleteDef(DestReg);
19636b3f41edSDimitry Andric } else {
19646b3f41edSDimitry Andric PHIInfo.replaceDef(DestReg, NextDestReg);
19656b3f41edSDimitry Andric }
19666b3f41edSDimitry Andric }
19676b3f41edSDimitry Andric }
19686b3f41edSDimitry Andric
containsDef(MachineBasicBlock * MBB,LinearizedRegion * InnerRegion,unsigned Register)19696b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::containsDef(MachineBasicBlock *MBB,
19706b3f41edSDimitry Andric LinearizedRegion *InnerRegion,
19716b3f41edSDimitry Andric unsigned Register) {
19726b3f41edSDimitry Andric return getDefInstr(Register)->getParent() == MBB ||
19736b3f41edSDimitry Andric InnerRegion->contains(getDefInstr(Register)->getParent());
19746b3f41edSDimitry Andric }
19756b3f41edSDimitry Andric
rewriteLiveOutRegs(MachineBasicBlock * IfBB,MachineBasicBlock * CodeBB,MachineBasicBlock * MergeBB,LinearizedRegion * InnerRegion,LinearizedRegion * LRegion)19766b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::rewriteLiveOutRegs(MachineBasicBlock *IfBB,
19776b3f41edSDimitry Andric MachineBasicBlock *CodeBB,
19786b3f41edSDimitry Andric MachineBasicBlock *MergeBB,
19796b3f41edSDimitry Andric LinearizedRegion *InnerRegion,
19806b3f41edSDimitry Andric LinearizedRegion *LRegion) {
19816b3f41edSDimitry Andric DenseSet<unsigned> *LiveOuts = InnerRegion->getLiveOuts();
19826b3f41edSDimitry Andric SmallVector<unsigned, 4> OldLiveOuts;
19836b3f41edSDimitry Andric bool IsSingleBB = InnerRegion->getEntry() == InnerRegion->getExit();
19846b3f41edSDimitry Andric for (auto OLI : *LiveOuts) {
19856b3f41edSDimitry Andric OldLiveOuts.push_back(OLI);
19866b3f41edSDimitry Andric }
19876b3f41edSDimitry Andric
19886b3f41edSDimitry Andric for (auto LI : OldLiveOuts) {
1989eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "LiveOut: " << printReg(LI, TRI));
19906b3f41edSDimitry Andric if (!containsDef(CodeBB, InnerRegion, LI) ||
19916b3f41edSDimitry Andric (!IsSingleBB && (getDefInstr(LI)->getParent() == LRegion->getExit()))) {
1992c0981da4SDimitry Andric // If the register simply lives through the CodeBB, we don't have
19936b3f41edSDimitry Andric // to rewrite anything since the register is not defined in this
19946b3f41edSDimitry Andric // part of the code.
1995eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "- through");
19966b3f41edSDimitry Andric continue;
19976b3f41edSDimitry Andric }
1998eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
19996b3f41edSDimitry Andric unsigned Reg = LI;
20006b3f41edSDimitry Andric if (/*!PHIInfo.isSource(Reg) &&*/ Reg != InnerRegion->getBBSelectRegOut()) {
20016b3f41edSDimitry Andric // If the register is live out, we do want to create a phi,
2002c0981da4SDimitry Andric // unless it is from the Exit block, because in that case there
20036b3f41edSDimitry Andric // is already a PHI, and no need to create a new one.
20046b3f41edSDimitry Andric
20056b3f41edSDimitry Andric // If the register is just a live out def and not part of a phi
20066b3f41edSDimitry Andric // chain, we need to create a PHI node to handle the if region,
20076b3f41edSDimitry Andric // and replace all uses outside of the region with the new dest
20086b3f41edSDimitry Andric // register, unless it is the outgoing BB select register. We have
2009c0981da4SDimitry Andric // already created phi nodes for these.
20106b3f41edSDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(Reg);
20111d5ae102SDimitry Andric Register PHIDestReg = MRI->createVirtualRegister(RegClass);
20121d5ae102SDimitry Andric Register IfSourceReg = MRI->createVirtualRegister(RegClass);
20136b3f41edSDimitry Andric // Create initializer, this value is never used, but is needed
20146b3f41edSDimitry Andric // to satisfy SSA.
2015eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Initializer for reg: " << printReg(Reg) << "\n");
20166b3f41edSDimitry Andric TII->materializeImmediate(*IfBB, IfBB->getFirstTerminator(), DebugLoc(),
20176b3f41edSDimitry Andric IfSourceReg, 0);
20186b3f41edSDimitry Andric
20196b3f41edSDimitry Andric InnerRegion->replaceRegisterOutsideRegion(Reg, PHIDestReg, true, MRI);
2020eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Insert Non-Chained Live out PHI\n");
20216b3f41edSDimitry Andric insertMergePHI(IfBB, InnerRegion->getExit(), MergeBB, PHIDestReg,
20226b3f41edSDimitry Andric IfSourceReg, Reg, true);
20236b3f41edSDimitry Andric }
20246b3f41edSDimitry Andric }
20256b3f41edSDimitry Andric
20266b3f41edSDimitry Andric // Handle the chained definitions in PHIInfo, checking if this basic block
20276b3f41edSDimitry Andric // is a source block for a definition.
20286b3f41edSDimitry Andric SmallVector<unsigned, 4> Sources;
20296b3f41edSDimitry Andric if (PHIInfo.findSourcesFromMBB(CodeBB, Sources)) {
2030eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting PHI Live Out from "
2031eb11fae6SDimitry Andric << printMBBReference(*CodeBB) << "\n");
20326b3f41edSDimitry Andric for (auto SI : Sources) {
20336b3f41edSDimitry Andric unsigned DestReg;
20346b3f41edSDimitry Andric PHIInfo.findDest(SI, CodeBB, DestReg);
20356b3f41edSDimitry Andric insertChainedPHI(IfBB, CodeBB, MergeBB, InnerRegion, DestReg, SI);
20366b3f41edSDimitry Andric }
2037eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Insertion done.\n");
20386b3f41edSDimitry Andric }
20396b3f41edSDimitry Andric
2040eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
20416b3f41edSDimitry Andric }
20426b3f41edSDimitry Andric
prunePHIInfo(MachineBasicBlock * MBB)20436b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::prunePHIInfo(MachineBasicBlock *MBB) {
2044eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Before PHI Prune\n");
2045eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
20466b3f41edSDimitry Andric SmallVector<std::tuple<unsigned, unsigned, MachineBasicBlock *>, 4>
20476b3f41edSDimitry Andric ElimiatedSources;
20486b3f41edSDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE;
20496b3f41edSDimitry Andric ++DRI) {
20506b3f41edSDimitry Andric
20516b3f41edSDimitry Andric unsigned DestReg = *DRI;
20526b3f41edSDimitry Andric auto SE = PHIInfo.sources_end(DestReg);
20536b3f41edSDimitry Andric
20546b3f41edSDimitry Andric bool MBBContainsPHISource = false;
20556b3f41edSDimitry Andric // Check if there is a PHI source in this MBB
20566b3f41edSDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) {
20576b3f41edSDimitry Andric unsigned SourceReg = (*SRI).first;
20586b3f41edSDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg)));
20596b3f41edSDimitry Andric if (Def->getParent()->getParent() == MBB) {
20606b3f41edSDimitry Andric MBBContainsPHISource = true;
20616b3f41edSDimitry Andric }
20626b3f41edSDimitry Andric }
20636b3f41edSDimitry Andric
20646b3f41edSDimitry Andric // If so, all other sources are useless since we know this block
20656b3f41edSDimitry Andric // is always executed when the region is executed.
20666b3f41edSDimitry Andric if (MBBContainsPHISource) {
20676b3f41edSDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) {
20686b3f41edSDimitry Andric PHILinearize::PHISourceT Source = *SRI;
20696b3f41edSDimitry Andric unsigned SourceReg = Source.first;
20706b3f41edSDimitry Andric MachineBasicBlock *SourceMBB = Source.second;
20716b3f41edSDimitry Andric MachineOperand *Def = &(*(MRI->def_begin(SourceReg)));
20726b3f41edSDimitry Andric if (Def->getParent()->getParent() != MBB) {
2073e3b55780SDimitry Andric ElimiatedSources.push_back(std::tuple(DestReg, SourceReg, SourceMBB));
20746b3f41edSDimitry Andric }
20756b3f41edSDimitry Andric }
20766b3f41edSDimitry Andric }
20776b3f41edSDimitry Andric }
20786b3f41edSDimitry Andric
20796b3f41edSDimitry Andric // Remove the PHI sources that are in the given MBB
20806b3f41edSDimitry Andric for (auto &SourceInfo : ElimiatedSources) {
20816b3f41edSDimitry Andric PHIInfo.removeSource(std::get<0>(SourceInfo), std::get<1>(SourceInfo),
20826b3f41edSDimitry Andric std::get<2>(SourceInfo));
20836b3f41edSDimitry Andric }
2084eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "After PHI Prune\n");
2085eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
20866b3f41edSDimitry Andric }
20876b3f41edSDimitry Andric
createEntryPHI(LinearizedRegion * CurrentRegion,unsigned DestReg)20886b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegion,
20896b3f41edSDimitry Andric unsigned DestReg) {
20906b3f41edSDimitry Andric MachineBasicBlock *Entry = CurrentRegion->getEntry();
20916b3f41edSDimitry Andric MachineBasicBlock *Exit = CurrentRegion->getExit();
20926b3f41edSDimitry Andric
2093eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExit: " << Exit->getNumber() << " Pred: "
2094eb11fae6SDimitry Andric << (*(Entry->pred_begin()))->getNumber() << "\n");
20956b3f41edSDimitry Andric
20966b3f41edSDimitry Andric int NumSources = 0;
20976b3f41edSDimitry Andric auto SE = PHIInfo.sources_end(DestReg);
20986b3f41edSDimitry Andric
20996b3f41edSDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) {
21006b3f41edSDimitry Andric NumSources++;
21016b3f41edSDimitry Andric }
21026b3f41edSDimitry Andric
21036b3f41edSDimitry Andric if (NumSources == 1) {
21046b3f41edSDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg);
21056b3f41edSDimitry Andric unsigned SourceReg = (*SRI).first;
21066b3f41edSDimitry Andric replaceRegisterWith(DestReg, SourceReg);
21076b3f41edSDimitry Andric } else {
21086b3f41edSDimitry Andric const DebugLoc &DL = Entry->findDebugLoc(Entry->begin());
21096b3f41edSDimitry Andric MachineInstrBuilder MIB = BuildMI(*Entry, Entry->instr_begin(), DL,
21106b3f41edSDimitry Andric TII->get(TargetOpcode::PHI), DestReg);
2111eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Entry PHI " << printReg(DestReg, TRI) << " = PHI(");
21126b3f41edSDimitry Andric
21136b3f41edSDimitry Andric unsigned CurrentBackedgeReg = 0;
21146b3f41edSDimitry Andric
21156b3f41edSDimitry Andric for (auto SRI = PHIInfo.sources_begin(DestReg); SRI != SE; ++SRI) {
21166b3f41edSDimitry Andric unsigned SourceReg = (*SRI).first;
21176b3f41edSDimitry Andric
21186b3f41edSDimitry Andric if (CurrentRegion->contains((*SRI).second)) {
21196b3f41edSDimitry Andric if (CurrentBackedgeReg == 0) {
21206b3f41edSDimitry Andric CurrentBackedgeReg = SourceReg;
21216b3f41edSDimitry Andric } else {
21226b3f41edSDimitry Andric MachineInstr *PHIDefInstr = getDefInstr(SourceReg);
21236b3f41edSDimitry Andric MachineBasicBlock *PHIDefMBB = PHIDefInstr->getParent();
21246b3f41edSDimitry Andric const TargetRegisterClass *RegClass =
21256b3f41edSDimitry Andric MRI->getRegClass(CurrentBackedgeReg);
21261d5ae102SDimitry Andric Register NewBackedgeReg = MRI->createVirtualRegister(RegClass);
21276b3f41edSDimitry Andric MachineInstrBuilder BackedgePHI =
21286b3f41edSDimitry Andric BuildMI(*PHIDefMBB, PHIDefMBB->instr_begin(), DL,
21296b3f41edSDimitry Andric TII->get(TargetOpcode::PHI), NewBackedgeReg);
21306b3f41edSDimitry Andric BackedgePHI.addReg(CurrentBackedgeReg);
21316b3f41edSDimitry Andric BackedgePHI.addMBB(getPHIPred(*PHIDefInstr, 0));
21326b3f41edSDimitry Andric BackedgePHI.addReg(getPHISourceReg(*PHIDefInstr, 1));
21336b3f41edSDimitry Andric BackedgePHI.addMBB((*SRI).second);
21346b3f41edSDimitry Andric CurrentBackedgeReg = NewBackedgeReg;
2135eb11fae6SDimitry Andric LLVM_DEBUG(dbgs()
2136eb11fae6SDimitry Andric << "Inserting backedge PHI: "
2137044eb2f6SDimitry Andric << printReg(NewBackedgeReg, TRI) << " = PHI("
2138044eb2f6SDimitry Andric << printReg(CurrentBackedgeReg, TRI) << ", "
2139eb11fae6SDimitry Andric << printMBBReference(*getPHIPred(*PHIDefInstr, 0)) << ", "
2140eb11fae6SDimitry Andric << printReg(getPHISourceReg(*PHIDefInstr, 1), TRI) << ", "
2141eb11fae6SDimitry Andric << printMBBReference(*(*SRI).second));
21426b3f41edSDimitry Andric }
21436b3f41edSDimitry Andric } else {
21446b3f41edSDimitry Andric MIB.addReg(SourceReg);
21456b3f41edSDimitry Andric MIB.addMBB((*SRI).second);
2146eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(SourceReg, TRI) << ", "
2147044eb2f6SDimitry Andric << printMBBReference(*(*SRI).second) << ", ");
21486b3f41edSDimitry Andric }
21496b3f41edSDimitry Andric }
21506b3f41edSDimitry Andric
21516b3f41edSDimitry Andric // Add the final backedge register source to the entry phi
21526b3f41edSDimitry Andric if (CurrentBackedgeReg != 0) {
21536b3f41edSDimitry Andric MIB.addReg(CurrentBackedgeReg);
21546b3f41edSDimitry Andric MIB.addMBB(Exit);
2155eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(CurrentBackedgeReg, TRI) << ", "
2156044eb2f6SDimitry Andric << printMBBReference(*Exit) << ")\n");
21576b3f41edSDimitry Andric } else {
2158eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ")\n");
21596b3f41edSDimitry Andric }
21606b3f41edSDimitry Andric }
21616b3f41edSDimitry Andric }
21626b3f41edSDimitry Andric
createEntryPHIs(LinearizedRegion * CurrentRegion)21636b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::createEntryPHIs(LinearizedRegion *CurrentRegion) {
2164eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
21656b3f41edSDimitry Andric
21666b3f41edSDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE;
21676b3f41edSDimitry Andric ++DRI) {
21686b3f41edSDimitry Andric
21696b3f41edSDimitry Andric unsigned DestReg = *DRI;
21706b3f41edSDimitry Andric createEntryPHI(CurrentRegion, DestReg);
21716b3f41edSDimitry Andric }
21726b3f41edSDimitry Andric PHIInfo.clear();
21736b3f41edSDimitry Andric }
21746b3f41edSDimitry Andric
replaceRegisterWith(unsigned Register,class Register NewRegister)2175b60736ecSDimitry Andric void AMDGPUMachineCFGStructurizer::replaceRegisterWith(
2176b60736ecSDimitry Andric unsigned Register, class Register NewRegister) {
21776b3f41edSDimitry Andric assert(Register != NewRegister && "Cannot replace a reg with itself");
21786b3f41edSDimitry Andric
21796b3f41edSDimitry Andric for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Register),
21806b3f41edSDimitry Andric E = MRI->reg_end();
21816b3f41edSDimitry Andric I != E;) {
21826b3f41edSDimitry Andric MachineOperand &O = *I;
21836b3f41edSDimitry Andric ++I;
2184b60736ecSDimitry Andric if (NewRegister.isPhysical()) {
2185eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Trying to substitute physical register: "
2186044eb2f6SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo())
21876b3f41edSDimitry Andric << "\n");
21886b3f41edSDimitry Andric llvm_unreachable("Cannot substitute physical registers");
21896b3f41edSDimitry Andric // We don't handle physical registers, but if we need to
21906b3f41edSDimitry Andric // in the future This is how we do it:
21916b3f41edSDimitry Andric // O.substPhysReg(NewRegister, *TRI);
21926b3f41edSDimitry Andric } else {
2193eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing register: "
2194044eb2f6SDimitry Andric << printReg(Register, MRI->getTargetRegisterInfo())
21956b3f41edSDimitry Andric << " with "
2196044eb2f6SDimitry Andric << printReg(NewRegister, MRI->getTargetRegisterInfo())
21976b3f41edSDimitry Andric << "\n");
21986b3f41edSDimitry Andric O.setReg(NewRegister);
21996b3f41edSDimitry Andric }
22006b3f41edSDimitry Andric }
22016b3f41edSDimitry Andric PHIInfo.deleteDef(Register);
22026b3f41edSDimitry Andric
22036b3f41edSDimitry Andric getRegionMRT()->replaceLiveOutReg(Register, NewRegister);
22046b3f41edSDimitry Andric
2205eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
22066b3f41edSDimitry Andric }
22076b3f41edSDimitry Andric
resolvePHIInfos(MachineBasicBlock * FunctionEntry)22086b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::resolvePHIInfos(MachineBasicBlock *FunctionEntry) {
2209eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Resolve PHI Infos\n");
2210eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
22116b3f41edSDimitry Andric for (auto DRI = PHIInfo.dests_begin(), DE = PHIInfo.dests_end(); DRI != DE;
22126b3f41edSDimitry Andric ++DRI) {
22136b3f41edSDimitry Andric unsigned DestReg = *DRI;
2214eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI) << "\n");
22156b3f41edSDimitry Andric auto SRI = PHIInfo.sources_begin(DestReg);
22166b3f41edSDimitry Andric unsigned SourceReg = (*SRI).first;
2217eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "DestReg: " << printReg(DestReg, TRI)
2218044eb2f6SDimitry Andric << " SourceReg: " << printReg(SourceReg, TRI) << "\n");
22196b3f41edSDimitry Andric
22206b3f41edSDimitry Andric assert(PHIInfo.sources_end(DestReg) == ++SRI &&
22216b3f41edSDimitry Andric "More than one phi source in entry node");
22226b3f41edSDimitry Andric replaceRegisterWith(DestReg, SourceReg);
22236b3f41edSDimitry Andric }
22246b3f41edSDimitry Andric }
22256b3f41edSDimitry Andric
isFunctionEntryBlock(MachineBasicBlock * MBB)22266b3f41edSDimitry Andric static bool isFunctionEntryBlock(MachineBasicBlock *MBB) {
22276b3f41edSDimitry Andric return ((&(*(MBB->getParent()->begin()))) == MBB);
22286b3f41edSDimitry Andric }
22296b3f41edSDimitry Andric
createIfRegion(MachineBasicBlock * MergeBB,MachineBasicBlock * CodeBB,LinearizedRegion * CurrentRegion,unsigned BBSelectRegIn,unsigned BBSelectRegOut)22306b3f41edSDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion(
22316b3f41edSDimitry Andric MachineBasicBlock *MergeBB, MachineBasicBlock *CodeBB,
22326b3f41edSDimitry Andric LinearizedRegion *CurrentRegion, unsigned BBSelectRegIn,
22336b3f41edSDimitry Andric unsigned BBSelectRegOut) {
22346b3f41edSDimitry Andric if (isFunctionEntryBlock(CodeBB) && !CurrentRegion->getHasLoop()) {
22356b3f41edSDimitry Andric // Handle non-loop function entry block.
22366b3f41edSDimitry Andric // We need to allow loops to the entry block and then
22376b3f41edSDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut);
22386b3f41edSDimitry Andric resolvePHIInfos(CodeBB);
22396b3f41edSDimitry Andric removeExternalCFGSuccessors(CodeBB);
22406b3f41edSDimitry Andric CodeBB->addSuccessor(MergeBB);
22416b3f41edSDimitry Andric CurrentRegion->addMBB(CodeBB);
22426b3f41edSDimitry Andric return nullptr;
22436b3f41edSDimitry Andric }
22446b3f41edSDimitry Andric if (CurrentRegion->getEntry() == CodeBB && !CurrentRegion->getHasLoop()) {
22456b3f41edSDimitry Andric // Handle non-loop region entry block.
22466b3f41edSDimitry Andric MachineFunction *MF = MergeBB->getParent();
22476b3f41edSDimitry Andric auto MergeIter = MergeBB->getIterator();
22486b3f41edSDimitry Andric auto CodeBBStartIter = CodeBB->getIterator();
22496b3f41edSDimitry Andric auto CodeBBEndIter = ++(CodeBB->getIterator());
22506b3f41edSDimitry Andric if (CodeBBEndIter != MergeIter) {
22516b3f41edSDimitry Andric MF->splice(MergeIter, CodeBBStartIter, CodeBBEndIter);
22526b3f41edSDimitry Andric }
22536b3f41edSDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, BBSelectRegOut);
22546b3f41edSDimitry Andric prunePHIInfo(CodeBB);
22556b3f41edSDimitry Andric createEntryPHIs(CurrentRegion);
22566b3f41edSDimitry Andric removeExternalCFGSuccessors(CodeBB);
22576b3f41edSDimitry Andric CodeBB->addSuccessor(MergeBB);
22586b3f41edSDimitry Andric CurrentRegion->addMBB(CodeBB);
22596b3f41edSDimitry Andric return nullptr;
2260ac9a064cSDimitry Andric }
22616b3f41edSDimitry Andric // Handle internal block.
22626b3f41edSDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(BBSelectRegIn);
22631d5ae102SDimitry Andric Register CodeBBSelectReg = MRI->createVirtualRegister(RegClass);
22646b3f41edSDimitry Andric rewriteCodeBBTerminator(CodeBB, MergeBB, CodeBBSelectReg);
22656b3f41edSDimitry Andric bool IsRegionEntryBB = CurrentRegion->getEntry() == CodeBB;
22666b3f41edSDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeBB, CodeBB, CodeBB,
22676b3f41edSDimitry Andric BBSelectRegIn, IsRegionEntryBB);
22686b3f41edSDimitry Andric CurrentRegion->addMBB(IfBB);
22696b3f41edSDimitry Andric // If this is the entry block we need to make the If block the new
22706b3f41edSDimitry Andric // linearized region entry.
22716b3f41edSDimitry Andric if (IsRegionEntryBB) {
22726b3f41edSDimitry Andric CurrentRegion->setEntry(IfBB);
22736b3f41edSDimitry Andric
22746b3f41edSDimitry Andric if (CurrentRegion->getHasLoop()) {
22756b3f41edSDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit();
22766b3f41edSDimitry Andric MachineBasicBlock *ETrueBB = nullptr;
22776b3f41edSDimitry Andric MachineBasicBlock *EFalseBB = nullptr;
22786b3f41edSDimitry Andric SmallVector<MachineOperand, 1> ECond;
22796b3f41edSDimitry Andric
22806b3f41edSDimitry Andric const DebugLoc &DL = DebugLoc();
22816b3f41edSDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond);
22826b3f41edSDimitry Andric TII->removeBranch(*RegionExit);
22836b3f41edSDimitry Andric
22846b3f41edSDimitry Andric // We need to create a backedge if there is a loop
2285ac9a064cSDimitry Andric Register Reg =
2286ac9a064cSDimitry Andric TII->insertNE(RegionExit, RegionExit->instr_end(), DL,
22876b3f41edSDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(),
22886b3f41edSDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber());
2289ac9a064cSDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true);
22906b3f41edSDimitry Andric ArrayRef<MachineOperand> Cond(RegOp);
2291eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: ");
2292ac9a064cSDimitry Andric LLVM_DEBUG(RegOp.print(dbgs(), TRI));
2293eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
22946b3f41edSDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit,
22956b3f41edSDimitry Andric Cond, DebugLoc());
22966b3f41edSDimitry Andric RegionExit->addSuccessor(CurrentRegion->getEntry());
22976b3f41edSDimitry Andric }
22986b3f41edSDimitry Andric }
22996b3f41edSDimitry Andric CurrentRegion->addMBB(CodeBB);
23006b3f41edSDimitry Andric LinearizedRegion InnerRegion(CodeBB, MRI, TRI, PHIInfo);
23016b3f41edSDimitry Andric
23026b3f41edSDimitry Andric InnerRegion.setParent(CurrentRegion);
2303eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (BB)\n");
23046b3f41edSDimitry Andric insertMergePHI(IfBB, CodeBB, MergeBB, BBSelectRegOut, BBSelectRegIn,
23056b3f41edSDimitry Andric CodeBBSelectReg);
23066b3f41edSDimitry Andric InnerRegion.addMBB(MergeBB);
23076b3f41edSDimitry Andric
2308eb11fae6SDimitry Andric LLVM_DEBUG(InnerRegion.print(dbgs(), TRI));
23096b3f41edSDimitry Andric rewriteLiveOutRegs(IfBB, CodeBB, MergeBB, &InnerRegion, CurrentRegion);
23106b3f41edSDimitry Andric extractKilledPHIs(CodeBB);
2311ac9a064cSDimitry Andric if (IsRegionEntryBB)
23126b3f41edSDimitry Andric createEntryPHIs(CurrentRegion);
23136b3f41edSDimitry Andric return IfBB;
23146b3f41edSDimitry Andric }
23156b3f41edSDimitry Andric
createIfRegion(MachineBasicBlock * MergeBB,LinearizedRegion * InnerRegion,LinearizedRegion * CurrentRegion,MachineBasicBlock * SelectBB,unsigned BBSelectRegIn,unsigned BBSelectRegOut)23166b3f41edSDimitry Andric MachineBasicBlock *AMDGPUMachineCFGStructurizer::createIfRegion(
23176b3f41edSDimitry Andric MachineBasicBlock *MergeBB, LinearizedRegion *InnerRegion,
23186b3f41edSDimitry Andric LinearizedRegion *CurrentRegion, MachineBasicBlock *SelectBB,
23196b3f41edSDimitry Andric unsigned BBSelectRegIn, unsigned BBSelectRegOut) {
23206b3f41edSDimitry Andric unsigned CodeBBSelectReg =
23216b3f41edSDimitry Andric InnerRegion->getRegionMRT()->getInnerOutputRegister();
23226b3f41edSDimitry Andric MachineBasicBlock *CodeEntryBB = InnerRegion->getEntry();
23236b3f41edSDimitry Andric MachineBasicBlock *CodeExitBB = InnerRegion->getExit();
23246b3f41edSDimitry Andric MachineBasicBlock *IfBB = createIfBlock(MergeBB, CodeEntryBB, CodeExitBB,
23256b3f41edSDimitry Andric SelectBB, BBSelectRegIn, true);
23266b3f41edSDimitry Andric CurrentRegion->addMBB(IfBB);
23276b3f41edSDimitry Andric bool isEntry = CurrentRegion->getEntry() == InnerRegion->getEntry();
23286b3f41edSDimitry Andric if (isEntry) {
23296b3f41edSDimitry Andric
23306b3f41edSDimitry Andric if (CurrentRegion->getHasLoop()) {
23316b3f41edSDimitry Andric MachineBasicBlock *RegionExit = CurrentRegion->getExit();
23326b3f41edSDimitry Andric MachineBasicBlock *ETrueBB = nullptr;
23336b3f41edSDimitry Andric MachineBasicBlock *EFalseBB = nullptr;
23346b3f41edSDimitry Andric SmallVector<MachineOperand, 1> ECond;
23356b3f41edSDimitry Andric
23366b3f41edSDimitry Andric const DebugLoc &DL = DebugLoc();
23376b3f41edSDimitry Andric TII->analyzeBranch(*RegionExit, ETrueBB, EFalseBB, ECond);
23386b3f41edSDimitry Andric TII->removeBranch(*RegionExit);
23396b3f41edSDimitry Andric
23406b3f41edSDimitry Andric // We need to create a backedge if there is a loop
2341b60736ecSDimitry Andric Register Reg =
23426b3f41edSDimitry Andric TII->insertNE(RegionExit, RegionExit->instr_end(), DL,
23436b3f41edSDimitry Andric CurrentRegion->getRegionMRT()->getInnerOutputRegister(),
23446b3f41edSDimitry Andric CurrentRegion->getRegionMRT()->getEntry()->getNumber());
23456b3f41edSDimitry Andric MachineOperand RegOp = MachineOperand::CreateReg(Reg, false, false, true);
23466b3f41edSDimitry Andric ArrayRef<MachineOperand> Cond(RegOp);
2347eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "RegionExitReg: ");
2348eb11fae6SDimitry Andric LLVM_DEBUG(Cond[0].print(dbgs(), TRI));
2349eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
23506b3f41edSDimitry Andric TII->insertBranch(*RegionExit, CurrentRegion->getEntry(), RegionExit,
23516b3f41edSDimitry Andric Cond, DebugLoc());
23526b3f41edSDimitry Andric RegionExit->addSuccessor(IfBB);
23536b3f41edSDimitry Andric }
23546b3f41edSDimitry Andric }
23556b3f41edSDimitry Andric CurrentRegion->addMBBs(InnerRegion);
2356eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Insert BB Select PHI (region)\n");
23576b3f41edSDimitry Andric insertMergePHI(IfBB, CodeExitBB, MergeBB, BBSelectRegOut, BBSelectRegIn,
23586b3f41edSDimitry Andric CodeBBSelectReg);
23596b3f41edSDimitry Andric
23606b3f41edSDimitry Andric rewriteLiveOutRegs(IfBB, /* CodeEntryBB */ CodeExitBB, MergeBB, InnerRegion,
23616b3f41edSDimitry Andric CurrentRegion);
23626b3f41edSDimitry Andric
23636b3f41edSDimitry Andric rewriteRegionEntryPHIs(InnerRegion, IfBB);
23646b3f41edSDimitry Andric
23656b3f41edSDimitry Andric if (isEntry) {
23666b3f41edSDimitry Andric CurrentRegion->setEntry(IfBB);
23676b3f41edSDimitry Andric }
23686b3f41edSDimitry Andric
23696b3f41edSDimitry Andric if (isEntry) {
23706b3f41edSDimitry Andric createEntryPHIs(CurrentRegion);
23716b3f41edSDimitry Andric }
23726b3f41edSDimitry Andric
23736b3f41edSDimitry Andric return IfBB;
23746b3f41edSDimitry Andric }
23756b3f41edSDimitry Andric
splitLoopPHI(MachineInstr & PHI,MachineBasicBlock * Entry,MachineBasicBlock * EntrySucc,LinearizedRegion * LRegion)23766b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHI(MachineInstr &PHI,
23776b3f41edSDimitry Andric MachineBasicBlock *Entry,
23786b3f41edSDimitry Andric MachineBasicBlock *EntrySucc,
23796b3f41edSDimitry Andric LinearizedRegion *LRegion) {
23806b3f41edSDimitry Andric SmallVector<unsigned, 2> PHIRegionIndices;
23816b3f41edSDimitry Andric getPHIRegionIndices(LRegion, PHI, PHIRegionIndices);
23826b3f41edSDimitry Andric
23836b3f41edSDimitry Andric assert(PHIRegionIndices.size() == 1);
23846b3f41edSDimitry Andric
23856b3f41edSDimitry Andric unsigned RegionIndex = PHIRegionIndices[0];
23866b3f41edSDimitry Andric unsigned RegionSourceReg = getPHISourceReg(PHI, RegionIndex);
23876b3f41edSDimitry Andric MachineBasicBlock *RegionSourceMBB = getPHIPred(PHI, RegionIndex);
23886b3f41edSDimitry Andric unsigned PHIDest = getPHIDestReg(PHI);
23896b3f41edSDimitry Andric unsigned PHISource = PHIDest;
23906b3f41edSDimitry Andric unsigned ReplaceReg;
23916b3f41edSDimitry Andric
23926b3f41edSDimitry Andric if (shrinkPHI(PHI, PHIRegionIndices, &ReplaceReg)) {
23936b3f41edSDimitry Andric PHISource = ReplaceReg;
23946b3f41edSDimitry Andric }
23956b3f41edSDimitry Andric
23966b3f41edSDimitry Andric const TargetRegisterClass *RegClass = MRI->getRegClass(PHIDest);
23971d5ae102SDimitry Andric Register NewDestReg = MRI->createVirtualRegister(RegClass);
23986b3f41edSDimitry Andric LRegion->replaceRegisterInsideRegion(PHIDest, NewDestReg, false, MRI);
23996b3f41edSDimitry Andric MachineInstrBuilder MIB =
24006b3f41edSDimitry Andric BuildMI(*EntrySucc, EntrySucc->instr_begin(), PHI.getDebugLoc(),
24016b3f41edSDimitry Andric TII->get(TargetOpcode::PHI), NewDestReg);
2402eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Split Entry PHI " << printReg(NewDestReg, TRI)
2403eb11fae6SDimitry Andric << " = PHI(");
24046b3f41edSDimitry Andric MIB.addReg(PHISource);
24056b3f41edSDimitry Andric MIB.addMBB(Entry);
2406eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << printReg(PHISource, TRI) << ", "
2407044eb2f6SDimitry Andric << printMBBReference(*Entry));
24086b3f41edSDimitry Andric MIB.addReg(RegionSourceReg);
24096b3f41edSDimitry Andric MIB.addMBB(RegionSourceMBB);
2410eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " ," << printReg(RegionSourceReg, TRI) << ", "
2411044eb2f6SDimitry Andric << printMBBReference(*RegionSourceMBB) << ")\n");
24126b3f41edSDimitry Andric }
24136b3f41edSDimitry Andric
splitLoopPHIs(MachineBasicBlock * Entry,MachineBasicBlock * EntrySucc,LinearizedRegion * LRegion)24146b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::splitLoopPHIs(MachineBasicBlock *Entry,
24156b3f41edSDimitry Andric MachineBasicBlock *EntrySucc,
24166b3f41edSDimitry Andric LinearizedRegion *LRegion) {
24176b3f41edSDimitry Andric SmallVector<MachineInstr *, 2> PHIs;
24186b3f41edSDimitry Andric collectPHIs(Entry, PHIs);
24196b3f41edSDimitry Andric
2420e3b55780SDimitry Andric for (auto *PHII : PHIs) {
24216b3f41edSDimitry Andric splitLoopPHI(*PHII, Entry, EntrySucc, LRegion);
24226b3f41edSDimitry Andric }
24236b3f41edSDimitry Andric }
24246b3f41edSDimitry Andric
24256b3f41edSDimitry Andric // Split the exit block so that we can insert a end control flow
24266b3f41edSDimitry Andric MachineBasicBlock *
splitExit(LinearizedRegion * LRegion)24276b3f41edSDimitry Andric AMDGPUMachineCFGStructurizer::splitExit(LinearizedRegion *LRegion) {
24286b3f41edSDimitry Andric auto MRTRegion = LRegion->getRegionMRT();
24296b3f41edSDimitry Andric auto Exit = LRegion->getExit();
24306b3f41edSDimitry Andric auto MF = Exit->getParent();
24316b3f41edSDimitry Andric auto Succ = MRTRegion->getSucc();
24326b3f41edSDimitry Andric
24336b3f41edSDimitry Andric auto NewExit = MF->CreateMachineBasicBlock();
24346b3f41edSDimitry Andric auto AfterExitIter = Exit->getIterator();
24356b3f41edSDimitry Andric AfterExitIter++;
24366b3f41edSDimitry Andric MF->insert(AfterExitIter, NewExit);
24376b3f41edSDimitry Andric Exit->removeSuccessor(Succ);
24386b3f41edSDimitry Andric Exit->addSuccessor(NewExit);
24396b3f41edSDimitry Andric NewExit->addSuccessor(Succ);
24406b3f41edSDimitry Andric insertUnconditionalBranch(NewExit, Succ);
24416b3f41edSDimitry Andric LRegion->addMBB(NewExit);
24426b3f41edSDimitry Andric LRegion->setExit(NewExit);
24436b3f41edSDimitry Andric
2444eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Created new exit block: " << NewExit->getNumber()
2445eb11fae6SDimitry Andric << "\n");
24466b3f41edSDimitry Andric
24476b3f41edSDimitry Andric // Replace any PHI Predecessors in the successor with NewExit
24486b3f41edSDimitry Andric for (auto &II : *Succ) {
24496b3f41edSDimitry Andric MachineInstr &Instr = II;
24506b3f41edSDimitry Andric
24516b3f41edSDimitry Andric // If we are past the PHI instructions we are done
24526b3f41edSDimitry Andric if (!Instr.isPHI())
24536b3f41edSDimitry Andric break;
24546b3f41edSDimitry Andric
24556b3f41edSDimitry Andric int numPreds = getPHINumInputs(Instr);
24566b3f41edSDimitry Andric for (int i = 0; i < numPreds; ++i) {
24576b3f41edSDimitry Andric auto Pred = getPHIPred(Instr, i);
24586b3f41edSDimitry Andric if (Pred == Exit) {
24596b3f41edSDimitry Andric setPhiPred(Instr, i, NewExit);
24606b3f41edSDimitry Andric }
24616b3f41edSDimitry Andric }
24626b3f41edSDimitry Andric }
24636b3f41edSDimitry Andric
24646b3f41edSDimitry Andric return NewExit;
24656b3f41edSDimitry Andric }
24666b3f41edSDimitry Andric
split(MachineBasicBlock::iterator I)24676b3f41edSDimitry Andric static MachineBasicBlock *split(MachineBasicBlock::iterator I) {
24686b3f41edSDimitry Andric // Create the fall-through block.
24696b3f41edSDimitry Andric MachineBasicBlock *MBB = (*I).getParent();
24706b3f41edSDimitry Andric MachineFunction *MF = MBB->getParent();
24716b3f41edSDimitry Andric MachineBasicBlock *SuccMBB = MF->CreateMachineBasicBlock();
24726b3f41edSDimitry Andric auto MBBIter = ++(MBB->getIterator());
24736b3f41edSDimitry Andric MF->insert(MBBIter, SuccMBB);
24746b3f41edSDimitry Andric SuccMBB->transferSuccessorsAndUpdatePHIs(MBB);
24756b3f41edSDimitry Andric MBB->addSuccessor(SuccMBB);
24766b3f41edSDimitry Andric
24776b3f41edSDimitry Andric // Splice the code over.
24786b3f41edSDimitry Andric SuccMBB->splice(SuccMBB->end(), MBB, I, MBB->end());
24796b3f41edSDimitry Andric
24806b3f41edSDimitry Andric return SuccMBB;
24816b3f41edSDimitry Andric }
24826b3f41edSDimitry Andric
24836b3f41edSDimitry Andric // Split the entry block separating PHI-nodes and the rest of the code
24846b3f41edSDimitry Andric // This is needed to insert an initializer for the bb select register
24856b3f41edSDimitry Andric // inloop regions.
24866b3f41edSDimitry Andric
24876b3f41edSDimitry Andric MachineBasicBlock *
splitEntry(LinearizedRegion * LRegion)24886b3f41edSDimitry Andric AMDGPUMachineCFGStructurizer::splitEntry(LinearizedRegion *LRegion) {
24896b3f41edSDimitry Andric MachineBasicBlock *Entry = LRegion->getEntry();
24906b3f41edSDimitry Andric MachineBasicBlock *EntrySucc = split(Entry->getFirstNonPHI());
24916b3f41edSDimitry Andric MachineBasicBlock *Exit = LRegion->getExit();
24926b3f41edSDimitry Andric
2493eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Split " << printMBBReference(*Entry) << " to "
2494044eb2f6SDimitry Andric << printMBBReference(*Entry) << " -> "
2495044eb2f6SDimitry Andric << printMBBReference(*EntrySucc) << "\n");
24966b3f41edSDimitry Andric LRegion->addMBB(EntrySucc);
24976b3f41edSDimitry Andric
24986b3f41edSDimitry Andric // Make the backedge go to Entry Succ
24996b3f41edSDimitry Andric if (Exit->isSuccessor(Entry)) {
25006b3f41edSDimitry Andric Exit->removeSuccessor(Entry);
25016b3f41edSDimitry Andric }
25026b3f41edSDimitry Andric Exit->addSuccessor(EntrySucc);
25036b3f41edSDimitry Andric MachineInstr &Branch = *(Exit->instr_rbegin());
25046b3f41edSDimitry Andric for (auto &UI : Branch.uses()) {
25056b3f41edSDimitry Andric if (UI.isMBB() && UI.getMBB() == Entry) {
25066b3f41edSDimitry Andric UI.setMBB(EntrySucc);
25076b3f41edSDimitry Andric }
25086b3f41edSDimitry Andric }
25096b3f41edSDimitry Andric
25106b3f41edSDimitry Andric splitLoopPHIs(Entry, EntrySucc, LRegion);
25116b3f41edSDimitry Andric
25126b3f41edSDimitry Andric return EntrySucc;
25136b3f41edSDimitry Andric }
25146b3f41edSDimitry Andric
25156b3f41edSDimitry Andric LinearizedRegion *
initLinearizedRegion(RegionMRT * Region)25166b3f41edSDimitry Andric AMDGPUMachineCFGStructurizer::initLinearizedRegion(RegionMRT *Region) {
25176b3f41edSDimitry Andric LinearizedRegion *LRegion = Region->getLinearizedRegion();
25186b3f41edSDimitry Andric LRegion->initLiveOut(Region, MRI, TRI, PHIInfo);
25196b3f41edSDimitry Andric LRegion->setEntry(Region->getEntry());
25206b3f41edSDimitry Andric return LRegion;
25216b3f41edSDimitry Andric }
25226b3f41edSDimitry Andric
removeOldExitPreds(RegionMRT * Region)25236b3f41edSDimitry Andric static void removeOldExitPreds(RegionMRT *Region) {
25246b3f41edSDimitry Andric MachineBasicBlock *Exit = Region->getSucc();
25256b3f41edSDimitry Andric if (Exit == nullptr) {
25266b3f41edSDimitry Andric return;
25276b3f41edSDimitry Andric }
25286b3f41edSDimitry Andric for (MachineBasicBlock::pred_iterator PI = Exit->pred_begin(),
25296b3f41edSDimitry Andric E = Exit->pred_end();
25306b3f41edSDimitry Andric PI != E; ++PI) {
25316b3f41edSDimitry Andric if (Region->contains(*PI)) {
25326b3f41edSDimitry Andric (*PI)->removeSuccessor(Exit);
25336b3f41edSDimitry Andric }
25346b3f41edSDimitry Andric }
25356b3f41edSDimitry Andric }
25366b3f41edSDimitry Andric
mbbHasBackEdge(MachineBasicBlock * MBB,SmallPtrSet<MachineBasicBlock *,8> & MBBs)25376b3f41edSDimitry Andric static bool mbbHasBackEdge(MachineBasicBlock *MBB,
25386b3f41edSDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) {
2539c0981da4SDimitry Andric for (MachineBasicBlock *Succ : MBB->successors())
2540c0981da4SDimitry Andric if (MBBs.contains(Succ))
25416b3f41edSDimitry Andric return true;
25426b3f41edSDimitry Andric return false;
25436b3f41edSDimitry Andric }
25446b3f41edSDimitry Andric
containsNewBackedge(MRT * Tree,SmallPtrSet<MachineBasicBlock *,8> & MBBs)25456b3f41edSDimitry Andric static bool containsNewBackedge(MRT *Tree,
25466b3f41edSDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &MBBs) {
25476b3f41edSDimitry Andric // Need to traverse this in reverse since it is in post order.
25486b3f41edSDimitry Andric if (Tree == nullptr)
25496b3f41edSDimitry Andric return false;
25506b3f41edSDimitry Andric
25516b3f41edSDimitry Andric if (Tree->isMBB()) {
25526b3f41edSDimitry Andric MachineBasicBlock *MBB = Tree->getMBBMRT()->getMBB();
25536b3f41edSDimitry Andric MBBs.insert(MBB);
25546b3f41edSDimitry Andric if (mbbHasBackEdge(MBB, MBBs)) {
25556b3f41edSDimitry Andric return true;
25566b3f41edSDimitry Andric }
25576b3f41edSDimitry Andric } else {
25586b3f41edSDimitry Andric RegionMRT *Region = Tree->getRegionMRT();
2559c0981da4SDimitry Andric for (MRT *C : llvm::reverse(*Region->getChildren()))
2560c0981da4SDimitry Andric if (containsNewBackedge(C, MBBs))
25616b3f41edSDimitry Andric return true;
25626b3f41edSDimitry Andric }
25636b3f41edSDimitry Andric return false;
25646b3f41edSDimitry Andric }
25656b3f41edSDimitry Andric
containsNewBackedge(RegionMRT * Region)25666b3f41edSDimitry Andric static bool containsNewBackedge(RegionMRT *Region) {
25676b3f41edSDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> MBBs;
25686b3f41edSDimitry Andric return containsNewBackedge(Region, MBBs);
25696b3f41edSDimitry Andric }
25706b3f41edSDimitry Andric
structurizeComplexRegion(RegionMRT * Region)25716b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeComplexRegion(RegionMRT *Region) {
25726b3f41edSDimitry Andric auto *LRegion = initLinearizedRegion(Region);
25736b3f41edSDimitry Andric LRegion->setHasLoop(containsNewBackedge(Region));
25746b3f41edSDimitry Andric MachineBasicBlock *LastMerge = createLinearizedExitBlock(Region);
25756b3f41edSDimitry Andric MachineBasicBlock *CurrentMerge = LastMerge;
25766b3f41edSDimitry Andric LRegion->addMBB(LastMerge);
25776b3f41edSDimitry Andric LRegion->setExit(LastMerge);
25786b3f41edSDimitry Andric
25796b3f41edSDimitry Andric rewriteRegionExitPHIs(Region, LastMerge, LRegion);
25806b3f41edSDimitry Andric removeOldExitPreds(Region);
25816b3f41edSDimitry Andric
2582eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
25836b3f41edSDimitry Andric
25846b3f41edSDimitry Andric SetVector<MRT *> *Children = Region->getChildren();
2585eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region Start===============\n");
25866b3f41edSDimitry Andric if (LRegion->getHasLoop()) {
2587eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: Yes\n");
25886b3f41edSDimitry Andric } else {
2589eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Has Backedge: No\n");
25906b3f41edSDimitry Andric }
25916b3f41edSDimitry Andric
25926b3f41edSDimitry Andric unsigned BBSelectRegIn;
25936b3f41edSDimitry Andric unsigned BBSelectRegOut;
2594ac9a064cSDimitry Andric for (MRT *Child : *Children) {
2595eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "CurrentRegion: \n");
2596eb11fae6SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI));
25976b3f41edSDimitry Andric
25986b3f41edSDimitry Andric if (Child->isRegion()) {
25996b3f41edSDimitry Andric
26006b3f41edSDimitry Andric LinearizedRegion *InnerLRegion =
26016b3f41edSDimitry Andric Child->getRegionMRT()->getLinearizedRegion();
26026b3f41edSDimitry Andric // We found the block is the exit of an inner region, we need
26036b3f41edSDimitry Andric // to put it in the current linearized region.
26046b3f41edSDimitry Andric
2605eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing region: ");
2606eb11fae6SDimitry Andric LLVM_DEBUG(InnerLRegion->print(dbgs(), TRI));
2607eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
26086b3f41edSDimitry Andric
26096b3f41edSDimitry Andric MachineBasicBlock *InnerEntry = InnerLRegion->getEntry();
26106b3f41edSDimitry Andric if ((&(*(InnerEntry->getParent()->begin()))) == InnerEntry) {
26116b3f41edSDimitry Andric // Entry has already been linearized, no need to do this region.
26126b3f41edSDimitry Andric unsigned OuterSelect = InnerLRegion->getBBSelectRegOut();
26136b3f41edSDimitry Andric unsigned InnerSelectReg =
26146b3f41edSDimitry Andric InnerLRegion->getRegionMRT()->getInnerOutputRegister();
26156b3f41edSDimitry Andric replaceRegisterWith(InnerSelectReg, OuterSelect),
26166b3f41edSDimitry Andric resolvePHIInfos(InnerEntry);
26176b3f41edSDimitry Andric if (!InnerLRegion->getExit()->isSuccessor(CurrentMerge))
26186b3f41edSDimitry Andric InnerLRegion->getExit()->addSuccessor(CurrentMerge);
26196b3f41edSDimitry Andric continue;
26206b3f41edSDimitry Andric }
26216b3f41edSDimitry Andric
26226b3f41edSDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut();
26236b3f41edSDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn();
26246b3f41edSDimitry Andric
2625eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI)
26266b3f41edSDimitry Andric << "\n");
2627eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI)
26286b3f41edSDimitry Andric << "\n");
26296b3f41edSDimitry Andric
26306b3f41edSDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge;
26316b3f41edSDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, InnerLRegion, LRegion,
26326b3f41edSDimitry Andric Child->getRegionMRT()->getEntry(),
26336b3f41edSDimitry Andric BBSelectRegIn, BBSelectRegOut);
26346b3f41edSDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd);
26356b3f41edSDimitry Andric } else {
26366b3f41edSDimitry Andric MachineBasicBlock *MBB = Child->getMBBMRT()->getMBB();
2637eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Linearizing block: " << MBB->getNumber() << "\n");
26386b3f41edSDimitry Andric
26396b3f41edSDimitry Andric if (MBB == getSingleExitNode(*(MBB->getParent()))) {
26406b3f41edSDimitry Andric // If this is the exit block then we need to skip to the next.
26416b3f41edSDimitry Andric // The "in" register will be transferred to "out" in the next
26426b3f41edSDimitry Andric // iteration.
26436b3f41edSDimitry Andric continue;
26446b3f41edSDimitry Andric }
26456b3f41edSDimitry Andric
26466b3f41edSDimitry Andric BBSelectRegOut = Child->getBBSelectRegOut();
26476b3f41edSDimitry Andric BBSelectRegIn = Child->getBBSelectRegIn();
26486b3f41edSDimitry Andric
2649eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegIn: " << printReg(BBSelectRegIn, TRI)
26506b3f41edSDimitry Andric << "\n");
2651eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "BBSelectRegOut: " << printReg(BBSelectRegOut, TRI)
26526b3f41edSDimitry Andric << "\n");
26536b3f41edSDimitry Andric
26546b3f41edSDimitry Andric MachineBasicBlock *IfEnd = CurrentMerge;
26556b3f41edSDimitry Andric // This is a basic block that is not part of an inner region, we
26566b3f41edSDimitry Andric // need to put it in the current linearized region.
26576b3f41edSDimitry Andric CurrentMerge = createIfRegion(CurrentMerge, MBB, LRegion, BBSelectRegIn,
26586b3f41edSDimitry Andric BBSelectRegOut);
26596b3f41edSDimitry Andric if (CurrentMerge) {
26606b3f41edSDimitry Andric TII->convertNonUniformIfRegion(CurrentMerge, IfEnd);
26616b3f41edSDimitry Andric }
26626b3f41edSDimitry Andric
2663eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
26646b3f41edSDimitry Andric }
26656b3f41edSDimitry Andric }
26666b3f41edSDimitry Andric
26676b3f41edSDimitry Andric LRegion->removeFalseRegisterKills(MRI);
26686b3f41edSDimitry Andric
26696b3f41edSDimitry Andric if (LRegion->getHasLoop()) {
26706b3f41edSDimitry Andric MachineBasicBlock *NewSucc = splitEntry(LRegion);
26716b3f41edSDimitry Andric if (isFunctionEntryBlock(LRegion->getEntry())) {
26726b3f41edSDimitry Andric resolvePHIInfos(LRegion->getEntry());
26736b3f41edSDimitry Andric }
26746b3f41edSDimitry Andric const DebugLoc &DL = NewSucc->findDebugLoc(NewSucc->getFirstNonPHI());
26756b3f41edSDimitry Andric unsigned InReg = LRegion->getBBSelectRegIn();
26761d5ae102SDimitry Andric Register InnerSelectReg =
26776b3f41edSDimitry Andric MRI->createVirtualRegister(MRI->getRegClass(InReg));
26781d5ae102SDimitry Andric Register NewInReg = MRI->createVirtualRegister(MRI->getRegClass(InReg));
26796b3f41edSDimitry Andric TII->materializeImmediate(*(LRegion->getEntry()),
26806b3f41edSDimitry Andric LRegion->getEntry()->getFirstTerminator(), DL,
26816b3f41edSDimitry Andric NewInReg, Region->getEntry()->getNumber());
26826b3f41edSDimitry Andric // Need to be careful about updating the registers inside the region.
26836b3f41edSDimitry Andric LRegion->replaceRegisterInsideRegion(InReg, InnerSelectReg, false, MRI);
2684eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Loop BBSelect Merge PHI:\n");
26856b3f41edSDimitry Andric insertMergePHI(LRegion->getEntry(), LRegion->getExit(), NewSucc,
26866b3f41edSDimitry Andric InnerSelectReg, NewInReg,
26876b3f41edSDimitry Andric LRegion->getRegionMRT()->getInnerOutputRegister());
26886b3f41edSDimitry Andric splitExit(LRegion);
26896b3f41edSDimitry Andric TII->convertNonUniformLoopRegion(NewSucc, LastMerge);
26906b3f41edSDimitry Andric }
26916b3f41edSDimitry Andric
26926b3f41edSDimitry Andric if (Region->isRoot()) {
26936b3f41edSDimitry Andric TII->insertReturn(*LastMerge);
26946b3f41edSDimitry Andric }
26956b3f41edSDimitry Andric
2696eb11fae6SDimitry Andric LLVM_DEBUG(Region->getEntry()->getParent()->dump());
2697eb11fae6SDimitry Andric LLVM_DEBUG(LRegion->print(dbgs(), TRI));
2698eb11fae6SDimitry Andric LLVM_DEBUG(PHIInfo.dump(MRI));
26996b3f41edSDimitry Andric
2700eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "===========If Region End===============\n");
27016b3f41edSDimitry Andric
27026b3f41edSDimitry Andric Region->setLinearizedRegion(LRegion);
27036b3f41edSDimitry Andric return true;
27046b3f41edSDimitry Andric }
27056b3f41edSDimitry Andric
structurizeRegion(RegionMRT * Region)27066b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegion(RegionMRT *Region) {
27076b3f41edSDimitry Andric if (false && regionIsSimpleIf(Region)) {
27086b3f41edSDimitry Andric transformSimpleIfRegion(Region);
27096b3f41edSDimitry Andric return true;
27106b3f41edSDimitry Andric }
2711ac9a064cSDimitry Andric if (regionIsSequence(Region))
2712ac9a064cSDimitry Andric fixupRegionExits(Region);
2713ac9a064cSDimitry Andric else
2714ac9a064cSDimitry Andric structurizeComplexRegion(Region);
27156b3f41edSDimitry Andric return false;
27166b3f41edSDimitry Andric }
27176b3f41edSDimitry Andric
27186b3f41edSDimitry Andric static int structurize_once = 0;
27196b3f41edSDimitry Andric
structurizeRegions(RegionMRT * Region,bool isTopRegion)27206b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::structurizeRegions(RegionMRT *Region,
27216b3f41edSDimitry Andric bool isTopRegion) {
27226b3f41edSDimitry Andric bool Changed = false;
27236b3f41edSDimitry Andric
27246b3f41edSDimitry Andric auto Children = Region->getChildren();
2725e3b55780SDimitry Andric for (auto *CI : *Children) {
27266b3f41edSDimitry Andric if (CI->isRegion()) {
27276b3f41edSDimitry Andric Changed |= structurizeRegions(CI->getRegionMRT(), false);
27286b3f41edSDimitry Andric }
27296b3f41edSDimitry Andric }
27306b3f41edSDimitry Andric
27316b3f41edSDimitry Andric if (structurize_once < 2 || true) {
27326b3f41edSDimitry Andric Changed |= structurizeRegion(Region);
27336b3f41edSDimitry Andric structurize_once++;
27346b3f41edSDimitry Andric }
27356b3f41edSDimitry Andric return Changed;
27366b3f41edSDimitry Andric }
27376b3f41edSDimitry Andric
initFallthroughMap(MachineFunction & MF)27386b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::initFallthroughMap(MachineFunction &MF) {
2739eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough Map:\n");
27406b3f41edSDimitry Andric for (auto &MBBI : MF) {
27416b3f41edSDimitry Andric MachineBasicBlock *MBB = MBBI.getFallThrough();
27426b3f41edSDimitry Andric if (MBB != nullptr) {
2743eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Fallthrough: " << MBBI.getNumber() << " -> "
27446b3f41edSDimitry Andric << MBB->getNumber() << "\n");
27456b3f41edSDimitry Andric }
27466b3f41edSDimitry Andric FallthroughMap[&MBBI] = MBB;
27476b3f41edSDimitry Andric }
27486b3f41edSDimitry Andric }
27496b3f41edSDimitry Andric
createLinearizedRegion(RegionMRT * Region,unsigned SelectOut)27506b3f41edSDimitry Andric void AMDGPUMachineCFGStructurizer::createLinearizedRegion(RegionMRT *Region,
27516b3f41edSDimitry Andric unsigned SelectOut) {
27526b3f41edSDimitry Andric LinearizedRegion *LRegion = new LinearizedRegion();
27536b3f41edSDimitry Andric if (SelectOut) {
27546b3f41edSDimitry Andric LRegion->addLiveOut(SelectOut);
2755eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Add LiveOut (BBSelect): " << printReg(SelectOut, TRI)
27566b3f41edSDimitry Andric << "\n");
27576b3f41edSDimitry Andric }
27586b3f41edSDimitry Andric LRegion->setRegionMRT(Region);
27596b3f41edSDimitry Andric Region->setLinearizedRegion(LRegion);
27606b3f41edSDimitry Andric LRegion->setParent(Region->getParent()
27616b3f41edSDimitry Andric ? Region->getParent()->getLinearizedRegion()
27626b3f41edSDimitry Andric : nullptr);
27636b3f41edSDimitry Andric }
27646b3f41edSDimitry Andric
27656b3f41edSDimitry Andric unsigned
initializeSelectRegisters(MRT * MRT,unsigned SelectOut,MachineRegisterInfo * MRI,const SIInstrInfo * TII)27666b3f41edSDimitry Andric AMDGPUMachineCFGStructurizer::initializeSelectRegisters(MRT *MRT, unsigned SelectOut,
27676b3f41edSDimitry Andric MachineRegisterInfo *MRI,
27686b3f41edSDimitry Andric const SIInstrInfo *TII) {
27696b3f41edSDimitry Andric if (MRT->isRegion()) {
27706b3f41edSDimitry Andric RegionMRT *Region = MRT->getRegionMRT();
27716b3f41edSDimitry Andric Region->setBBSelectRegOut(SelectOut);
27726b3f41edSDimitry Andric unsigned InnerSelectOut = createBBSelectReg(TII, MRI);
27736b3f41edSDimitry Andric
27746b3f41edSDimitry Andric // Fixme: Move linearization creation to the original spot
27756b3f41edSDimitry Andric createLinearizedRegion(Region, SelectOut);
27766b3f41edSDimitry Andric
277777fc4c14SDimitry Andric for (auto *CI : *Region->getChildren())
277877fc4c14SDimitry Andric InnerSelectOut = initializeSelectRegisters(CI, InnerSelectOut, MRI, TII);
27796b3f41edSDimitry Andric MRT->setBBSelectRegIn(InnerSelectOut);
27806b3f41edSDimitry Andric return InnerSelectOut;
2781ac9a064cSDimitry Andric }
27826b3f41edSDimitry Andric MRT->setBBSelectRegOut(SelectOut);
27836b3f41edSDimitry Andric unsigned NewSelectIn = createBBSelectReg(TII, MRI);
27846b3f41edSDimitry Andric MRT->setBBSelectRegIn(NewSelectIn);
27856b3f41edSDimitry Andric return NewSelectIn;
27866b3f41edSDimitry Andric }
27876b3f41edSDimitry Andric
checkRegOnlyPHIInputs(MachineFunction & MF)27886b3f41edSDimitry Andric static void checkRegOnlyPHIInputs(MachineFunction &MF) {
27896b3f41edSDimitry Andric for (auto &MBBI : MF) {
2790ac9a064cSDimitry Andric for (MachineInstr &Instr : MBBI.instrs()) {
27916b3f41edSDimitry Andric if (Instr.isPHI()) {
27926b3f41edSDimitry Andric int numPreds = getPHINumInputs(Instr);
27936b3f41edSDimitry Andric for (int i = 0; i < numPreds; ++i) {
27946b3f41edSDimitry Andric assert(Instr.getOperand(i * 2 + 1).isReg() &&
27956b3f41edSDimitry Andric "PHI Operand not a register");
27966b3f41edSDimitry Andric }
27976b3f41edSDimitry Andric }
27986b3f41edSDimitry Andric }
27996b3f41edSDimitry Andric }
28006b3f41edSDimitry Andric }
28016b3f41edSDimitry Andric
runOnMachineFunction(MachineFunction & MF)28026b3f41edSDimitry Andric bool AMDGPUMachineCFGStructurizer::runOnMachineFunction(MachineFunction &MF) {
2803eb11fae6SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
28046b3f41edSDimitry Andric const SIInstrInfo *TII = ST.getInstrInfo();
28056b3f41edSDimitry Andric TRI = ST.getRegisterInfo();
28066b3f41edSDimitry Andric MRI = &(MF.getRegInfo());
28076b3f41edSDimitry Andric initFallthroughMap(MF);
28086b3f41edSDimitry Andric
28096b3f41edSDimitry Andric checkRegOnlyPHIInputs(MF);
2810eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER START----\n");
2811eb11fae6SDimitry Andric LLVM_DEBUG(MF.dump());
28126b3f41edSDimitry Andric
28136b3f41edSDimitry Andric Regions = &(getAnalysis<MachineRegionInfoPass>().getRegionInfo());
2814eb11fae6SDimitry Andric LLVM_DEBUG(Regions->dump());
28156b3f41edSDimitry Andric
28166b3f41edSDimitry Andric RegionMRT *RTree = MRT::buildMRT(MF, Regions, TII, MRI);
28176b3f41edSDimitry Andric setRegionMRT(RTree);
28186b3f41edSDimitry Andric initializeSelectRegisters(RTree, 0, MRI, TII);
2819eb11fae6SDimitry Andric LLVM_DEBUG(RTree->dump(TRI));
28206b3f41edSDimitry Andric bool result = structurizeRegions(RTree, true);
28216b3f41edSDimitry Andric delete RTree;
2822eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "----STRUCTURIZER END----\n");
28236b3f41edSDimitry Andric initFallthroughMap(MF);
28246b3f41edSDimitry Andric return result;
28256b3f41edSDimitry Andric }
28266b3f41edSDimitry Andric
2827044eb2f6SDimitry Andric char AMDGPUMachineCFGStructurizerID = AMDGPUMachineCFGStructurizer::ID;
2828044eb2f6SDimitry Andric
2829044eb2f6SDimitry Andric INITIALIZE_PASS_BEGIN(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer",
2830044eb2f6SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineRegionInfoPass)2831044eb2f6SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineRegionInfoPass)
2832044eb2f6SDimitry Andric INITIALIZE_PASS_END(AMDGPUMachineCFGStructurizer, "amdgpu-machine-cfg-structurizer",
2833044eb2f6SDimitry Andric "AMDGPU Machine CFG Structurizer", false, false)
2834044eb2f6SDimitry Andric
28356b3f41edSDimitry Andric FunctionPass *llvm::createAMDGPUMachineCFGStructurizerPass() {
28366b3f41edSDimitry Andric return new AMDGPUMachineCFGStructurizer();
28376b3f41edSDimitry Andric }
2838