10946e70aSDimitry Andric //===- RDFGraph.cpp -------------------------------------------------------===// 20946e70aSDimitry Andric // 30946e70aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40946e70aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50946e70aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60946e70aSDimitry Andric // 70946e70aSDimitry Andric //===----------------------------------------------------------------------===// 80946e70aSDimitry Andric // 90946e70aSDimitry Andric // Target-independent, SSA-based data flow graph for register data flow (RDF). 100946e70aSDimitry Andric // 110946e70aSDimitry Andric #include "llvm/ADT/BitVector.h" 120946e70aSDimitry Andric #include "llvm/ADT/STLExtras.h" 130946e70aSDimitry Andric #include "llvm/ADT/SetVector.h" 140946e70aSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 150946e70aSDimitry Andric #include "llvm/CodeGen/MachineDominanceFrontier.h" 160946e70aSDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 170946e70aSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 180946e70aSDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 190946e70aSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 200946e70aSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 2106c3fb27SDimitry Andric #include "llvm/CodeGen/RDFGraph.h" 220946e70aSDimitry Andric #include "llvm/CodeGen/RDFRegisters.h" 230946e70aSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 240946e70aSDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 250946e70aSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 260946e70aSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 270946e70aSDimitry Andric #include "llvm/IR/Function.h" 280946e70aSDimitry Andric #include "llvm/MC/LaneBitmask.h" 290946e70aSDimitry Andric #include "llvm/MC/MCInstrDesc.h" 300946e70aSDimitry Andric #include "llvm/Support/ErrorHandling.h" 310946e70aSDimitry Andric #include "llvm/Support/raw_ostream.h" 320946e70aSDimitry Andric #include <algorithm> 330946e70aSDimitry Andric #include <cassert> 340946e70aSDimitry Andric #include <cstdint> 350946e70aSDimitry Andric #include <cstring> 360946e70aSDimitry Andric #include <iterator> 370946e70aSDimitry Andric #include <set> 380946e70aSDimitry Andric #include <utility> 390946e70aSDimitry Andric #include <vector> 400946e70aSDimitry Andric 410946e70aSDimitry Andric // Printing functions. Have them here first, so that the rest of the code 420946e70aSDimitry Andric // can use them. 4306c3fb27SDimitry Andric namespace llvm::rdf { 440946e70aSDimitry Andric 450946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterRef> &P) { 4606c3fb27SDimitry Andric P.G.getPRI().print(OS, P.Obj); 470946e70aSDimitry Andric return OS; 480946e70aSDimitry Andric } 490946e70aSDimitry Andric 500946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<NodeId> &P) { 5106c3fb27SDimitry Andric if (P.Obj == 0) 5206c3fb27SDimitry Andric return OS << "null"; 530946e70aSDimitry Andric auto NA = P.G.addr<NodeBase *>(P.Obj); 540946e70aSDimitry Andric uint16_t Attrs = NA.Addr->getAttrs(); 550946e70aSDimitry Andric uint16_t Kind = NodeAttrs::kind(Attrs); 560946e70aSDimitry Andric uint16_t Flags = NodeAttrs::flags(Attrs); 570946e70aSDimitry Andric switch (NodeAttrs::type(Attrs)) { 580946e70aSDimitry Andric case NodeAttrs::Code: 590946e70aSDimitry Andric switch (Kind) { 6006c3fb27SDimitry Andric case NodeAttrs::Func: 6106c3fb27SDimitry Andric OS << 'f'; 6206c3fb27SDimitry Andric break; 6306c3fb27SDimitry Andric case NodeAttrs::Block: 6406c3fb27SDimitry Andric OS << 'b'; 6506c3fb27SDimitry Andric break; 6606c3fb27SDimitry Andric case NodeAttrs::Stmt: 6706c3fb27SDimitry Andric OS << 's'; 6806c3fb27SDimitry Andric break; 6906c3fb27SDimitry Andric case NodeAttrs::Phi: 7006c3fb27SDimitry Andric OS << 'p'; 7106c3fb27SDimitry Andric break; 7206c3fb27SDimitry Andric default: 7306c3fb27SDimitry Andric OS << "c?"; 7406c3fb27SDimitry Andric break; 750946e70aSDimitry Andric } 760946e70aSDimitry Andric break; 770946e70aSDimitry Andric case NodeAttrs::Ref: 780946e70aSDimitry Andric if (Flags & NodeAttrs::Undef) 790946e70aSDimitry Andric OS << '/'; 800946e70aSDimitry Andric if (Flags & NodeAttrs::Dead) 810946e70aSDimitry Andric OS << '\\'; 820946e70aSDimitry Andric if (Flags & NodeAttrs::Preserving) 830946e70aSDimitry Andric OS << '+'; 840946e70aSDimitry Andric if (Flags & NodeAttrs::Clobbering) 850946e70aSDimitry Andric OS << '~'; 860946e70aSDimitry Andric switch (Kind) { 8706c3fb27SDimitry Andric case NodeAttrs::Use: 8806c3fb27SDimitry Andric OS << 'u'; 8906c3fb27SDimitry Andric break; 9006c3fb27SDimitry Andric case NodeAttrs::Def: 9106c3fb27SDimitry Andric OS << 'd'; 9206c3fb27SDimitry Andric break; 9306c3fb27SDimitry Andric case NodeAttrs::Block: 9406c3fb27SDimitry Andric OS << 'b'; 9506c3fb27SDimitry Andric break; 9606c3fb27SDimitry Andric default: 9706c3fb27SDimitry Andric OS << "r?"; 9806c3fb27SDimitry Andric break; 990946e70aSDimitry Andric } 1000946e70aSDimitry Andric break; 1010946e70aSDimitry Andric default: 1020946e70aSDimitry Andric OS << '?'; 1030946e70aSDimitry Andric break; 1040946e70aSDimitry Andric } 1050946e70aSDimitry Andric OS << P.Obj; 1060946e70aSDimitry Andric if (Flags & NodeAttrs::Shadow) 1070946e70aSDimitry Andric OS << '"'; 1080946e70aSDimitry Andric return OS; 1090946e70aSDimitry Andric } 1100946e70aSDimitry Andric 11106c3fb27SDimitry Andric static void printRefHeader(raw_ostream &OS, const Ref RA, 1120946e70aSDimitry Andric const DataFlowGraph &G) { 11306c3fb27SDimitry Andric OS << Print(RA.Id, G) << '<' << Print(RA.Addr->getRegRef(G), G) << '>'; 1140946e70aSDimitry Andric if (RA.Addr->getFlags() & NodeAttrs::Fixed) 1150946e70aSDimitry Andric OS << '!'; 1160946e70aSDimitry Andric } 1170946e70aSDimitry Andric 11806c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Def> &P) { 1190946e70aSDimitry Andric printRefHeader(OS, P.Obj, P.G); 1200946e70aSDimitry Andric OS << '('; 1210946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getReachingDef()) 122bdd1243dSDimitry Andric OS << Print(N, P.G); 1230946e70aSDimitry Andric OS << ','; 1240946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getReachedDef()) 125bdd1243dSDimitry Andric OS << Print(N, P.G); 1260946e70aSDimitry Andric OS << ','; 1270946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getReachedUse()) 128bdd1243dSDimitry Andric OS << Print(N, P.G); 1290946e70aSDimitry Andric OS << "):"; 1300946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getSibling()) 131bdd1243dSDimitry Andric OS << Print(N, P.G); 1320946e70aSDimitry Andric return OS; 1330946e70aSDimitry Andric } 1340946e70aSDimitry Andric 13506c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Use> &P) { 1360946e70aSDimitry Andric printRefHeader(OS, P.Obj, P.G); 1370946e70aSDimitry Andric OS << '('; 1380946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getReachingDef()) 139bdd1243dSDimitry Andric OS << Print(N, P.G); 1400946e70aSDimitry Andric OS << "):"; 1410946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getSibling()) 142bdd1243dSDimitry Andric OS << Print(N, P.G); 1430946e70aSDimitry Andric return OS; 1440946e70aSDimitry Andric } 1450946e70aSDimitry Andric 14606c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<PhiUse> &P) { 1470946e70aSDimitry Andric printRefHeader(OS, P.Obj, P.G); 1480946e70aSDimitry Andric OS << '('; 1490946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getReachingDef()) 150bdd1243dSDimitry Andric OS << Print(N, P.G); 1510946e70aSDimitry Andric OS << ','; 1520946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getPredecessor()) 153bdd1243dSDimitry Andric OS << Print(N, P.G); 1540946e70aSDimitry Andric OS << "):"; 1550946e70aSDimitry Andric if (NodeId N = P.Obj.Addr->getSibling()) 156bdd1243dSDimitry Andric OS << Print(N, P.G); 1570946e70aSDimitry Andric return OS; 1580946e70aSDimitry Andric } 1590946e70aSDimitry Andric 16006c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Ref> &P) { 1610946e70aSDimitry Andric switch (P.Obj.Addr->getKind()) { 1620946e70aSDimitry Andric case NodeAttrs::Def: 1630946e70aSDimitry Andric OS << PrintNode<DefNode *>(P.Obj, P.G); 1640946e70aSDimitry Andric break; 1650946e70aSDimitry Andric case NodeAttrs::Use: 1660946e70aSDimitry Andric if (P.Obj.Addr->getFlags() & NodeAttrs::PhiRef) 1670946e70aSDimitry Andric OS << PrintNode<PhiUseNode *>(P.Obj, P.G); 1680946e70aSDimitry Andric else 1690946e70aSDimitry Andric OS << PrintNode<UseNode *>(P.Obj, P.G); 1700946e70aSDimitry Andric break; 1710946e70aSDimitry Andric } 1720946e70aSDimitry Andric return OS; 1730946e70aSDimitry Andric } 1740946e70aSDimitry Andric 1750946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<NodeList> &P) { 1760946e70aSDimitry Andric unsigned N = P.Obj.size(); 1770946e70aSDimitry Andric for (auto I : P.Obj) { 178bdd1243dSDimitry Andric OS << Print(I.Id, P.G); 1790946e70aSDimitry Andric if (--N) 1800946e70aSDimitry Andric OS << ' '; 1810946e70aSDimitry Andric } 1820946e70aSDimitry Andric return OS; 1830946e70aSDimitry Andric } 1840946e70aSDimitry Andric 1850946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<NodeSet> &P) { 1860946e70aSDimitry Andric unsigned N = P.Obj.size(); 1870946e70aSDimitry Andric for (auto I : P.Obj) { 188bdd1243dSDimitry Andric OS << Print(I, P.G); 1890946e70aSDimitry Andric if (--N) 1900946e70aSDimitry Andric OS << ' '; 1910946e70aSDimitry Andric } 1920946e70aSDimitry Andric return OS; 1930946e70aSDimitry Andric } 1940946e70aSDimitry Andric 1950946e70aSDimitry Andric namespace { 1960946e70aSDimitry Andric 19706c3fb27SDimitry Andric template <typename T> struct PrintListV { 1980946e70aSDimitry Andric PrintListV(const NodeList &L, const DataFlowGraph &G) : List(L), G(G) {} 1990946e70aSDimitry Andric 2000946e70aSDimitry Andric using Type = T; 2010946e70aSDimitry Andric const NodeList &List; 2020946e70aSDimitry Andric const DataFlowGraph &G; 2030946e70aSDimitry Andric }; 2040946e70aSDimitry Andric 2050946e70aSDimitry Andric template <typename T> 2060946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const PrintListV<T> &P) { 2070946e70aSDimitry Andric unsigned N = P.List.size(); 2080946e70aSDimitry Andric for (NodeAddr<T> A : P.List) { 2090946e70aSDimitry Andric OS << PrintNode<T>(A, P.G); 2100946e70aSDimitry Andric if (--N) 2110946e70aSDimitry Andric OS << ", "; 2120946e70aSDimitry Andric } 2130946e70aSDimitry Andric return OS; 2140946e70aSDimitry Andric } 2150946e70aSDimitry Andric 2160946e70aSDimitry Andric } // end anonymous namespace 2170946e70aSDimitry Andric 21806c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Phi> &P) { 219bdd1243dSDimitry Andric OS << Print(P.Obj.Id, P.G) << ": phi [" 2200946e70aSDimitry Andric << PrintListV<RefNode *>(P.Obj.Addr->members(P.G), P.G) << ']'; 2210946e70aSDimitry Andric return OS; 2220946e70aSDimitry Andric } 2230946e70aSDimitry Andric 22406c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Stmt> &P) { 2250946e70aSDimitry Andric const MachineInstr &MI = *P.Obj.Addr->getCode(); 2260946e70aSDimitry Andric unsigned Opc = MI.getOpcode(); 227bdd1243dSDimitry Andric OS << Print(P.Obj.Id, P.G) << ": " << P.G.getTII().getName(Opc); 2280946e70aSDimitry Andric // Print the target for calls and branches (for readability). 2290946e70aSDimitry Andric if (MI.isCall() || MI.isBranch()) { 2300946e70aSDimitry Andric MachineInstr::const_mop_iterator T = 23106c3fb27SDimitry Andric llvm::find_if(MI.operands(), [](const MachineOperand &Op) -> bool { 2320946e70aSDimitry Andric return Op.isMBB() || Op.isGlobal() || Op.isSymbol(); 2330946e70aSDimitry Andric }); 2340946e70aSDimitry Andric if (T != MI.operands_end()) { 2350946e70aSDimitry Andric OS << ' '; 2360946e70aSDimitry Andric if (T->isMBB()) 2370946e70aSDimitry Andric OS << printMBBReference(*T->getMBB()); 2380946e70aSDimitry Andric else if (T->isGlobal()) 2390946e70aSDimitry Andric OS << T->getGlobal()->getName(); 2400946e70aSDimitry Andric else if (T->isSymbol()) 2410946e70aSDimitry Andric OS << T->getSymbolName(); 2420946e70aSDimitry Andric } 2430946e70aSDimitry Andric } 2440946e70aSDimitry Andric OS << " [" << PrintListV<RefNode *>(P.Obj.Addr->members(P.G), P.G) << ']'; 2450946e70aSDimitry Andric return OS; 2460946e70aSDimitry Andric } 2470946e70aSDimitry Andric 24806c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Instr> &P) { 2490946e70aSDimitry Andric switch (P.Obj.Addr->getKind()) { 2500946e70aSDimitry Andric case NodeAttrs::Phi: 2510946e70aSDimitry Andric OS << PrintNode<PhiNode *>(P.Obj, P.G); 2520946e70aSDimitry Andric break; 2530946e70aSDimitry Andric case NodeAttrs::Stmt: 2540946e70aSDimitry Andric OS << PrintNode<StmtNode *>(P.Obj, P.G); 2550946e70aSDimitry Andric break; 2560946e70aSDimitry Andric default: 257bdd1243dSDimitry Andric OS << "instr? " << Print(P.Obj.Id, P.G); 2580946e70aSDimitry Andric break; 2590946e70aSDimitry Andric } 2600946e70aSDimitry Andric return OS; 2610946e70aSDimitry Andric } 2620946e70aSDimitry Andric 26306c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Block> &P) { 2640946e70aSDimitry Andric MachineBasicBlock *BB = P.Obj.Addr->getCode(); 2650946e70aSDimitry Andric unsigned NP = BB->pred_size(); 2660946e70aSDimitry Andric std::vector<int> Ns; 267*0fca6ea1SDimitry Andric auto PrintBBs = [&OS](const std::vector<int> &Ns) -> void { 2680946e70aSDimitry Andric unsigned N = Ns.size(); 2690946e70aSDimitry Andric for (int I : Ns) { 2700946e70aSDimitry Andric OS << "%bb." << I; 2710946e70aSDimitry Andric if (--N) 2720946e70aSDimitry Andric OS << ", "; 2730946e70aSDimitry Andric } 2740946e70aSDimitry Andric }; 2750946e70aSDimitry Andric 276bdd1243dSDimitry Andric OS << Print(P.Obj.Id, P.G) << ": --- " << printMBBReference(*BB) 2770946e70aSDimitry Andric << " --- preds(" << NP << "): "; 2780946e70aSDimitry Andric for (MachineBasicBlock *B : BB->predecessors()) 2790946e70aSDimitry Andric Ns.push_back(B->getNumber()); 2800946e70aSDimitry Andric PrintBBs(Ns); 2810946e70aSDimitry Andric 2820946e70aSDimitry Andric unsigned NS = BB->succ_size(); 2830946e70aSDimitry Andric OS << " succs(" << NS << "): "; 2840946e70aSDimitry Andric Ns.clear(); 2850946e70aSDimitry Andric for (MachineBasicBlock *B : BB->successors()) 2860946e70aSDimitry Andric Ns.push_back(B->getNumber()); 2870946e70aSDimitry Andric PrintBBs(Ns); 2880946e70aSDimitry Andric OS << '\n'; 2890946e70aSDimitry Andric 2900946e70aSDimitry Andric for (auto I : P.Obj.Addr->members(P.G)) 2910946e70aSDimitry Andric OS << PrintNode<InstrNode *>(I, P.G) << '\n'; 2920946e70aSDimitry Andric return OS; 2930946e70aSDimitry Andric } 2940946e70aSDimitry Andric 29506c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Func> &P) { 29606c3fb27SDimitry Andric OS << "DFG dump:[\n" 29706c3fb27SDimitry Andric << Print(P.Obj.Id, P.G) 29806c3fb27SDimitry Andric << ": Function: " << P.Obj.Addr->getCode()->getName() << '\n'; 2990946e70aSDimitry Andric for (auto I : P.Obj.Addr->members(P.G)) 3000946e70aSDimitry Andric OS << PrintNode<BlockNode *>(I, P.G) << '\n'; 3010946e70aSDimitry Andric OS << "]\n"; 3020946e70aSDimitry Andric return OS; 3030946e70aSDimitry Andric } 3040946e70aSDimitry Andric 3050946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterSet> &P) { 3060946e70aSDimitry Andric OS << '{'; 3070946e70aSDimitry Andric for (auto I : P.Obj) 308bdd1243dSDimitry Andric OS << ' ' << Print(I, P.G); 3090946e70aSDimitry Andric OS << " }"; 3100946e70aSDimitry Andric return OS; 3110946e70aSDimitry Andric } 3120946e70aSDimitry Andric 3130946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterAggr> &P) { 31406c3fb27SDimitry Andric OS << P.Obj; 3150946e70aSDimitry Andric return OS; 3160946e70aSDimitry Andric } 3170946e70aSDimitry Andric 3180946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 3190946e70aSDimitry Andric const Print<DataFlowGraph::DefStack> &P) { 3200946e70aSDimitry Andric for (auto I = P.Obj.top(), E = P.Obj.bottom(); I != E;) { 32106c3fb27SDimitry Andric OS << Print(I->Id, P.G) << '<' << Print(I->Addr->getRegRef(P.G), P.G) 32206c3fb27SDimitry Andric << '>'; 3230946e70aSDimitry Andric I.down(); 3240946e70aSDimitry Andric if (I != E) 3250946e70aSDimitry Andric OS << ' '; 3260946e70aSDimitry Andric } 3270946e70aSDimitry Andric return OS; 3280946e70aSDimitry Andric } 3290946e70aSDimitry Andric 3300946e70aSDimitry Andric // Node allocation functions. 3310946e70aSDimitry Andric // 3320946e70aSDimitry Andric // Node allocator is like a slab memory allocator: it allocates blocks of 3330946e70aSDimitry Andric // memory in sizes that are multiples of the size of a node. Each block has 3340946e70aSDimitry Andric // the same size. Nodes are allocated from the currently active block, and 3350946e70aSDimitry Andric // when it becomes full, a new one is created. 3360946e70aSDimitry Andric // There is a mapping scheme between node id and its location in a block, 3370946e70aSDimitry Andric // and within that block is described in the header file. 3380946e70aSDimitry Andric // 3390946e70aSDimitry Andric void NodeAllocator::startNewBlock() { 3400946e70aSDimitry Andric void *T = MemPool.Allocate(NodesPerBlock * NodeMemSize, NodeMemSize); 3410946e70aSDimitry Andric char *P = static_cast<char *>(T); 3420946e70aSDimitry Andric Blocks.push_back(P); 3430946e70aSDimitry Andric // Check if the block index is still within the allowed range, i.e. less 3440946e70aSDimitry Andric // than 2^N, where N is the number of bits in NodeId for the block index. 3450946e70aSDimitry Andric // BitsPerIndex is the number of bits per node index. 3460946e70aSDimitry Andric assert((Blocks.size() < ((size_t)1 << (8 * sizeof(NodeId) - BitsPerIndex))) && 3470946e70aSDimitry Andric "Out of bits for block index"); 3480946e70aSDimitry Andric ActiveEnd = P; 3490946e70aSDimitry Andric } 3500946e70aSDimitry Andric 3510946e70aSDimitry Andric bool NodeAllocator::needNewBlock() { 3520946e70aSDimitry Andric if (Blocks.empty()) 3530946e70aSDimitry Andric return true; 3540946e70aSDimitry Andric 3550946e70aSDimitry Andric char *ActiveBegin = Blocks.back(); 3560946e70aSDimitry Andric uint32_t Index = (ActiveEnd - ActiveBegin) / NodeMemSize; 3570946e70aSDimitry Andric return Index >= NodesPerBlock; 3580946e70aSDimitry Andric } 3590946e70aSDimitry Andric 36006c3fb27SDimitry Andric Node NodeAllocator::New() { 3610946e70aSDimitry Andric if (needNewBlock()) 3620946e70aSDimitry Andric startNewBlock(); 3630946e70aSDimitry Andric 3640946e70aSDimitry Andric uint32_t ActiveB = Blocks.size() - 1; 3650946e70aSDimitry Andric uint32_t Index = (ActiveEnd - Blocks[ActiveB]) / NodeMemSize; 36606c3fb27SDimitry Andric Node NA = {reinterpret_cast<NodeBase *>(ActiveEnd), makeId(ActiveB, Index)}; 3670946e70aSDimitry Andric ActiveEnd += NodeMemSize; 3680946e70aSDimitry Andric return NA; 3690946e70aSDimitry Andric } 3700946e70aSDimitry Andric 3710946e70aSDimitry Andric NodeId NodeAllocator::id(const NodeBase *P) const { 3720946e70aSDimitry Andric uintptr_t A = reinterpret_cast<uintptr_t>(P); 3730946e70aSDimitry Andric for (unsigned i = 0, n = Blocks.size(); i != n; ++i) { 3740946e70aSDimitry Andric uintptr_t B = reinterpret_cast<uintptr_t>(Blocks[i]); 3750946e70aSDimitry Andric if (A < B || A >= B + NodesPerBlock * NodeMemSize) 3760946e70aSDimitry Andric continue; 3770946e70aSDimitry Andric uint32_t Idx = (A - B) / NodeMemSize; 3780946e70aSDimitry Andric return makeId(i, Idx); 3790946e70aSDimitry Andric } 3800946e70aSDimitry Andric llvm_unreachable("Invalid node address"); 3810946e70aSDimitry Andric } 3820946e70aSDimitry Andric 3830946e70aSDimitry Andric void NodeAllocator::clear() { 3840946e70aSDimitry Andric MemPool.Reset(); 3850946e70aSDimitry Andric Blocks.clear(); 3860946e70aSDimitry Andric ActiveEnd = nullptr; 3870946e70aSDimitry Andric } 3880946e70aSDimitry Andric 3890946e70aSDimitry Andric // Insert node NA after "this" in the circular chain. 39006c3fb27SDimitry Andric void NodeBase::append(Node NA) { 3910946e70aSDimitry Andric NodeId Nx = Next; 3920946e70aSDimitry Andric // If NA is already "next", do nothing. 3930946e70aSDimitry Andric if (Next != NA.Id) { 3940946e70aSDimitry Andric Next = NA.Id; 3950946e70aSDimitry Andric NA.Addr->Next = Nx; 3960946e70aSDimitry Andric } 3970946e70aSDimitry Andric } 3980946e70aSDimitry Andric 3990946e70aSDimitry Andric // Fundamental node manipulator functions. 4000946e70aSDimitry Andric 4010946e70aSDimitry Andric // Obtain the register reference from a reference node. 4020946e70aSDimitry Andric RegisterRef RefNode::getRegRef(const DataFlowGraph &G) const { 4030946e70aSDimitry Andric assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref); 4040946e70aSDimitry Andric if (NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef) 40506c3fb27SDimitry Andric return G.unpack(RefData.PR); 40606c3fb27SDimitry Andric assert(RefData.Op != nullptr); 40706c3fb27SDimitry Andric return G.makeRegRef(*RefData.Op); 4080946e70aSDimitry Andric } 4090946e70aSDimitry Andric 4100946e70aSDimitry Andric // Set the register reference in the reference node directly (for references 4110946e70aSDimitry Andric // in phi nodes). 4120946e70aSDimitry Andric void RefNode::setRegRef(RegisterRef RR, DataFlowGraph &G) { 4130946e70aSDimitry Andric assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref); 4140946e70aSDimitry Andric assert(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef); 41506c3fb27SDimitry Andric RefData.PR = G.pack(RR); 4160946e70aSDimitry Andric } 4170946e70aSDimitry Andric 4180946e70aSDimitry Andric // Set the register reference in the reference node based on a machine 4190946e70aSDimitry Andric // operand (for references in statement nodes). 4200946e70aSDimitry Andric void RefNode::setRegRef(MachineOperand *Op, DataFlowGraph &G) { 4210946e70aSDimitry Andric assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref); 4220946e70aSDimitry Andric assert(!(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef)); 4230946e70aSDimitry Andric (void)G; 42406c3fb27SDimitry Andric RefData.Op = Op; 4250946e70aSDimitry Andric } 4260946e70aSDimitry Andric 4270946e70aSDimitry Andric // Get the owner of a given reference node. 42806c3fb27SDimitry Andric Node RefNode::getOwner(const DataFlowGraph &G) { 42906c3fb27SDimitry Andric Node NA = G.addr<NodeBase *>(getNext()); 4300946e70aSDimitry Andric 4310946e70aSDimitry Andric while (NA.Addr != this) { 4320946e70aSDimitry Andric if (NA.Addr->getType() == NodeAttrs::Code) 4330946e70aSDimitry Andric return NA; 4340946e70aSDimitry Andric NA = G.addr<NodeBase *>(NA.Addr->getNext()); 4350946e70aSDimitry Andric } 4360946e70aSDimitry Andric llvm_unreachable("No owner in circular list"); 4370946e70aSDimitry Andric } 4380946e70aSDimitry Andric 4390946e70aSDimitry Andric // Connect the def node to the reaching def node. 44006c3fb27SDimitry Andric void DefNode::linkToDef(NodeId Self, Def DA) { 44106c3fb27SDimitry Andric RefData.RD = DA.Id; 44206c3fb27SDimitry Andric RefData.Sib = DA.Addr->getReachedDef(); 4430946e70aSDimitry Andric DA.Addr->setReachedDef(Self); 4440946e70aSDimitry Andric } 4450946e70aSDimitry Andric 4460946e70aSDimitry Andric // Connect the use node to the reaching def node. 44706c3fb27SDimitry Andric void UseNode::linkToDef(NodeId Self, Def DA) { 44806c3fb27SDimitry Andric RefData.RD = DA.Id; 44906c3fb27SDimitry Andric RefData.Sib = DA.Addr->getReachedUse(); 4500946e70aSDimitry Andric DA.Addr->setReachedUse(Self); 4510946e70aSDimitry Andric } 4520946e70aSDimitry Andric 4530946e70aSDimitry Andric // Get the first member of the code node. 45406c3fb27SDimitry Andric Node CodeNode::getFirstMember(const DataFlowGraph &G) const { 45506c3fb27SDimitry Andric if (CodeData.FirstM == 0) 45606c3fb27SDimitry Andric return Node(); 45706c3fb27SDimitry Andric return G.addr<NodeBase *>(CodeData.FirstM); 4580946e70aSDimitry Andric } 4590946e70aSDimitry Andric 4600946e70aSDimitry Andric // Get the last member of the code node. 46106c3fb27SDimitry Andric Node CodeNode::getLastMember(const DataFlowGraph &G) const { 46206c3fb27SDimitry Andric if (CodeData.LastM == 0) 46306c3fb27SDimitry Andric return Node(); 46406c3fb27SDimitry Andric return G.addr<NodeBase *>(CodeData.LastM); 4650946e70aSDimitry Andric } 4660946e70aSDimitry Andric 4670946e70aSDimitry Andric // Add node NA at the end of the member list of the given code node. 46806c3fb27SDimitry Andric void CodeNode::addMember(Node NA, const DataFlowGraph &G) { 46906c3fb27SDimitry Andric Node ML = getLastMember(G); 4700946e70aSDimitry Andric if (ML.Id != 0) { 4710946e70aSDimitry Andric ML.Addr->append(NA); 4720946e70aSDimitry Andric } else { 47306c3fb27SDimitry Andric CodeData.FirstM = NA.Id; 4740946e70aSDimitry Andric NodeId Self = G.id(this); 4750946e70aSDimitry Andric NA.Addr->setNext(Self); 4760946e70aSDimitry Andric } 47706c3fb27SDimitry Andric CodeData.LastM = NA.Id; 4780946e70aSDimitry Andric } 4790946e70aSDimitry Andric 4800946e70aSDimitry Andric // Add node NA after member node MA in the given code node. 48106c3fb27SDimitry Andric void CodeNode::addMemberAfter(Node MA, Node NA, const DataFlowGraph &G) { 4820946e70aSDimitry Andric MA.Addr->append(NA); 48306c3fb27SDimitry Andric if (CodeData.LastM == MA.Id) 48406c3fb27SDimitry Andric CodeData.LastM = NA.Id; 4850946e70aSDimitry Andric } 4860946e70aSDimitry Andric 4870946e70aSDimitry Andric // Remove member node NA from the given code node. 48806c3fb27SDimitry Andric void CodeNode::removeMember(Node NA, const DataFlowGraph &G) { 48906c3fb27SDimitry Andric Node MA = getFirstMember(G); 4900946e70aSDimitry Andric assert(MA.Id != 0); 4910946e70aSDimitry Andric 4920946e70aSDimitry Andric // Special handling if the member to remove is the first member. 4930946e70aSDimitry Andric if (MA.Id == NA.Id) { 49406c3fb27SDimitry Andric if (CodeData.LastM == MA.Id) { 4950946e70aSDimitry Andric // If it is the only member, set both first and last to 0. 49606c3fb27SDimitry Andric CodeData.FirstM = CodeData.LastM = 0; 4970946e70aSDimitry Andric } else { 4980946e70aSDimitry Andric // Otherwise, advance the first member. 49906c3fb27SDimitry Andric CodeData.FirstM = MA.Addr->getNext(); 5000946e70aSDimitry Andric } 5010946e70aSDimitry Andric return; 5020946e70aSDimitry Andric } 5030946e70aSDimitry Andric 5040946e70aSDimitry Andric while (MA.Addr != this) { 5050946e70aSDimitry Andric NodeId MX = MA.Addr->getNext(); 5060946e70aSDimitry Andric if (MX == NA.Id) { 5070946e70aSDimitry Andric MA.Addr->setNext(NA.Addr->getNext()); 5080946e70aSDimitry Andric // If the member to remove happens to be the last one, update the 5090946e70aSDimitry Andric // LastM indicator. 51006c3fb27SDimitry Andric if (CodeData.LastM == NA.Id) 51106c3fb27SDimitry Andric CodeData.LastM = MA.Id; 5120946e70aSDimitry Andric return; 5130946e70aSDimitry Andric } 5140946e70aSDimitry Andric MA = G.addr<NodeBase *>(MX); 5150946e70aSDimitry Andric } 5160946e70aSDimitry Andric llvm_unreachable("No such member"); 5170946e70aSDimitry Andric } 5180946e70aSDimitry Andric 5190946e70aSDimitry Andric // Return the list of all members of the code node. 5200946e70aSDimitry Andric NodeList CodeNode::members(const DataFlowGraph &G) const { 52106c3fb27SDimitry Andric static auto True = [](Node) -> bool { return true; }; 5220946e70aSDimitry Andric return members_if(True, G); 5230946e70aSDimitry Andric } 5240946e70aSDimitry Andric 5250946e70aSDimitry Andric // Return the owner of the given instr node. 52606c3fb27SDimitry Andric Node InstrNode::getOwner(const DataFlowGraph &G) { 52706c3fb27SDimitry Andric Node NA = G.addr<NodeBase *>(getNext()); 5280946e70aSDimitry Andric 5290946e70aSDimitry Andric while (NA.Addr != this) { 5300946e70aSDimitry Andric assert(NA.Addr->getType() == NodeAttrs::Code); 5310946e70aSDimitry Andric if (NA.Addr->getKind() == NodeAttrs::Block) 5320946e70aSDimitry Andric return NA; 5330946e70aSDimitry Andric NA = G.addr<NodeBase *>(NA.Addr->getNext()); 5340946e70aSDimitry Andric } 5350946e70aSDimitry Andric llvm_unreachable("No owner in circular list"); 5360946e70aSDimitry Andric } 5370946e70aSDimitry Andric 5380946e70aSDimitry Andric // Add the phi node PA to the given block node. 53906c3fb27SDimitry Andric void BlockNode::addPhi(Phi PA, const DataFlowGraph &G) { 54006c3fb27SDimitry Andric Node M = getFirstMember(G); 5410946e70aSDimitry Andric if (M.Id == 0) { 5420946e70aSDimitry Andric addMember(PA, G); 5430946e70aSDimitry Andric return; 5440946e70aSDimitry Andric } 5450946e70aSDimitry Andric 5460946e70aSDimitry Andric assert(M.Addr->getType() == NodeAttrs::Code); 5470946e70aSDimitry Andric if (M.Addr->getKind() == NodeAttrs::Stmt) { 5480946e70aSDimitry Andric // If the first member of the block is a statement, insert the phi as 5490946e70aSDimitry Andric // the first member. 55006c3fb27SDimitry Andric CodeData.FirstM = PA.Id; 5510946e70aSDimitry Andric PA.Addr->setNext(M.Id); 5520946e70aSDimitry Andric } else { 5530946e70aSDimitry Andric // If the first member is a phi, find the last phi, and append PA to it. 5540946e70aSDimitry Andric assert(M.Addr->getKind() == NodeAttrs::Phi); 55506c3fb27SDimitry Andric Node MN = M; 5560946e70aSDimitry Andric do { 5570946e70aSDimitry Andric M = MN; 5580946e70aSDimitry Andric MN = G.addr<NodeBase *>(M.Addr->getNext()); 5590946e70aSDimitry Andric assert(MN.Addr->getType() == NodeAttrs::Code); 5600946e70aSDimitry Andric } while (MN.Addr->getKind() == NodeAttrs::Phi); 5610946e70aSDimitry Andric 5620946e70aSDimitry Andric // M is the last phi. 5630946e70aSDimitry Andric addMemberAfter(M, PA, G); 5640946e70aSDimitry Andric } 5650946e70aSDimitry Andric } 5660946e70aSDimitry Andric 5670946e70aSDimitry Andric // Find the block node corresponding to the machine basic block BB in the 5680946e70aSDimitry Andric // given func node. 56906c3fb27SDimitry Andric Block FuncNode::findBlock(const MachineBasicBlock *BB, 5700946e70aSDimitry Andric const DataFlowGraph &G) const { 57106c3fb27SDimitry Andric auto EqBB = [BB](Node NA) -> bool { return Block(NA).Addr->getCode() == BB; }; 5720946e70aSDimitry Andric NodeList Ms = members_if(EqBB, G); 5730946e70aSDimitry Andric if (!Ms.empty()) 5740946e70aSDimitry Andric return Ms[0]; 57506c3fb27SDimitry Andric return Block(); 5760946e70aSDimitry Andric } 5770946e70aSDimitry Andric 5780946e70aSDimitry Andric // Get the block node for the entry block in the given function. 57906c3fb27SDimitry Andric Block FuncNode::getEntryBlock(const DataFlowGraph &G) { 5800946e70aSDimitry Andric MachineBasicBlock *EntryB = &getCode()->front(); 5810946e70aSDimitry Andric return findBlock(EntryB, G); 5820946e70aSDimitry Andric } 5830946e70aSDimitry Andric 5840946e70aSDimitry Andric // Target operand information. 5850946e70aSDimitry Andric // 5860946e70aSDimitry Andric 5870946e70aSDimitry Andric // For a given instruction, check if there are any bits of RR that can remain 5880946e70aSDimitry Andric // unchanged across this def. 58906c3fb27SDimitry Andric bool TargetOperandInfo::isPreserving(const MachineInstr &In, 59006c3fb27SDimitry Andric unsigned OpNum) const { 5910946e70aSDimitry Andric return TII.isPredicated(In); 5920946e70aSDimitry Andric } 5930946e70aSDimitry Andric 5940946e70aSDimitry Andric // Check if the definition of RR produces an unspecified value. 59506c3fb27SDimitry Andric bool TargetOperandInfo::isClobbering(const MachineInstr &In, 59606c3fb27SDimitry Andric unsigned OpNum) const { 5970946e70aSDimitry Andric const MachineOperand &Op = In.getOperand(OpNum); 5980946e70aSDimitry Andric if (Op.isRegMask()) 5990946e70aSDimitry Andric return true; 6000946e70aSDimitry Andric assert(Op.isReg()); 6010946e70aSDimitry Andric if (In.isCall()) 6020946e70aSDimitry Andric if (Op.isDef() && Op.isDead()) 6030946e70aSDimitry Andric return true; 6040946e70aSDimitry Andric return false; 6050946e70aSDimitry Andric } 6060946e70aSDimitry Andric 6070946e70aSDimitry Andric // Check if the given instruction specifically requires 60806c3fb27SDimitry Andric bool TargetOperandInfo::isFixedReg(const MachineInstr &In, 60906c3fb27SDimitry Andric unsigned OpNum) const { 6100946e70aSDimitry Andric if (In.isCall() || In.isReturn() || In.isInlineAsm()) 6110946e70aSDimitry Andric return true; 6120946e70aSDimitry Andric // Check for a tail call. 6130946e70aSDimitry Andric if (In.isBranch()) 6140946e70aSDimitry Andric for (const MachineOperand &O : In.operands()) 6150946e70aSDimitry Andric if (O.isGlobal() || O.isSymbol()) 6160946e70aSDimitry Andric return true; 6170946e70aSDimitry Andric 6180946e70aSDimitry Andric const MCInstrDesc &D = In.getDesc(); 619bdd1243dSDimitry Andric if (D.implicit_defs().empty() && D.implicit_uses().empty()) 6200946e70aSDimitry Andric return false; 6210946e70aSDimitry Andric const MachineOperand &Op = In.getOperand(OpNum); 6220946e70aSDimitry Andric // If there is a sub-register, treat the operand as non-fixed. Currently, 6230946e70aSDimitry Andric // fixed registers are those that are listed in the descriptor as implicit 6240946e70aSDimitry Andric // uses or defs, and those lists do not allow sub-registers. 6250946e70aSDimitry Andric if (Op.getSubReg() != 0) 6260946e70aSDimitry Andric return false; 6270946e70aSDimitry Andric Register Reg = Op.getReg(); 628bdd1243dSDimitry Andric ArrayRef<MCPhysReg> ImpOps = 629bdd1243dSDimitry Andric Op.isDef() ? D.implicit_defs() : D.implicit_uses(); 630bdd1243dSDimitry Andric return is_contained(ImpOps, Reg); 6310946e70aSDimitry Andric } 6320946e70aSDimitry Andric 6330946e70aSDimitry Andric // 6340946e70aSDimitry Andric // The data flow graph construction. 6350946e70aSDimitry Andric // 6360946e70aSDimitry Andric 6370946e70aSDimitry Andric DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, 63806c3fb27SDimitry Andric const TargetRegisterInfo &tri, 63906c3fb27SDimitry Andric const MachineDominatorTree &mdt, 640bdd1243dSDimitry Andric const MachineDominanceFrontier &mdf) 641bdd1243dSDimitry Andric : DefaultTOI(std::make_unique<TargetOperandInfo>(tii)), MF(mf), TII(tii), 642bdd1243dSDimitry Andric TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(*DefaultTOI), 64306c3fb27SDimitry Andric LiveIns(PRI) {} 644bdd1243dSDimitry Andric 645bdd1243dSDimitry Andric DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, 64606c3fb27SDimitry Andric const TargetRegisterInfo &tri, 64706c3fb27SDimitry Andric const MachineDominatorTree &mdt, 64806c3fb27SDimitry Andric const MachineDominanceFrontier &mdf, 64906c3fb27SDimitry Andric const TargetOperandInfo &toi) 6500946e70aSDimitry Andric : MF(mf), TII(tii), TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(toi), 65106c3fb27SDimitry Andric LiveIns(PRI) {} 6520946e70aSDimitry Andric 6530946e70aSDimitry Andric // The implementation of the definition stack. 6540946e70aSDimitry Andric // Each register reference has its own definition stack. In particular, 6550946e70aSDimitry Andric // for a register references "Reg" and "Reg:subreg" will each have their 6560946e70aSDimitry Andric // own definition stacks. 6570946e70aSDimitry Andric 6580946e70aSDimitry Andric // Construct a stack iterator. 6590946e70aSDimitry Andric DataFlowGraph::DefStack::Iterator::Iterator(const DataFlowGraph::DefStack &S, 66006c3fb27SDimitry Andric bool Top) 66106c3fb27SDimitry Andric : DS(S) { 6620946e70aSDimitry Andric if (!Top) { 6630946e70aSDimitry Andric // Initialize to bottom. 6640946e70aSDimitry Andric Pos = 0; 6650946e70aSDimitry Andric return; 6660946e70aSDimitry Andric } 6670946e70aSDimitry Andric // Initialize to the top, i.e. top-most non-delimiter (or 0, if empty). 6680946e70aSDimitry Andric Pos = DS.Stack.size(); 6690946e70aSDimitry Andric while (Pos > 0 && DS.isDelimiter(DS.Stack[Pos - 1])) 6700946e70aSDimitry Andric Pos--; 6710946e70aSDimitry Andric } 6720946e70aSDimitry Andric 6730946e70aSDimitry Andric // Return the size of the stack, including block delimiters. 6740946e70aSDimitry Andric unsigned DataFlowGraph::DefStack::size() const { 6750946e70aSDimitry Andric unsigned S = 0; 6760946e70aSDimitry Andric for (auto I = top(), E = bottom(); I != E; I.down()) 6770946e70aSDimitry Andric S++; 6780946e70aSDimitry Andric return S; 6790946e70aSDimitry Andric } 6800946e70aSDimitry Andric 6810946e70aSDimitry Andric // Remove the top entry from the stack. Remove all intervening delimiters 6820946e70aSDimitry Andric // so that after this, the stack is either empty, or the top of the stack 6830946e70aSDimitry Andric // is a non-delimiter. 6840946e70aSDimitry Andric void DataFlowGraph::DefStack::pop() { 6850946e70aSDimitry Andric assert(!empty()); 6860946e70aSDimitry Andric unsigned P = nextDown(Stack.size()); 6870946e70aSDimitry Andric Stack.resize(P); 6880946e70aSDimitry Andric } 6890946e70aSDimitry Andric 6900946e70aSDimitry Andric // Push a delimiter for block node N on the stack. 6910946e70aSDimitry Andric void DataFlowGraph::DefStack::start_block(NodeId N) { 6920946e70aSDimitry Andric assert(N != 0); 69306c3fb27SDimitry Andric Stack.push_back(Def(nullptr, N)); 6940946e70aSDimitry Andric } 6950946e70aSDimitry Andric 6960946e70aSDimitry Andric // Remove all nodes from the top of the stack, until the delimited for 6970946e70aSDimitry Andric // block node N is encountered. Remove the delimiter as well. In effect, 6980946e70aSDimitry Andric // this will remove from the stack all definitions from block N. 6990946e70aSDimitry Andric void DataFlowGraph::DefStack::clear_block(NodeId N) { 7000946e70aSDimitry Andric assert(N != 0); 7010946e70aSDimitry Andric unsigned P = Stack.size(); 7020946e70aSDimitry Andric while (P > 0) { 7030946e70aSDimitry Andric bool Found = isDelimiter(Stack[P - 1], N); 7040946e70aSDimitry Andric P--; 7050946e70aSDimitry Andric if (Found) 7060946e70aSDimitry Andric break; 7070946e70aSDimitry Andric } 7080946e70aSDimitry Andric // This will also remove the delimiter, if found. 7090946e70aSDimitry Andric Stack.resize(P); 7100946e70aSDimitry Andric } 7110946e70aSDimitry Andric 7120946e70aSDimitry Andric // Move the stack iterator up by one. 7130946e70aSDimitry Andric unsigned DataFlowGraph::DefStack::nextUp(unsigned P) const { 7140946e70aSDimitry Andric // Get the next valid position after P (skipping all delimiters). 7150946e70aSDimitry Andric // The input position P does not have to point to a non-delimiter. 7160946e70aSDimitry Andric unsigned SS = Stack.size(); 7170946e70aSDimitry Andric bool IsDelim; 7180946e70aSDimitry Andric assert(P < SS); 7190946e70aSDimitry Andric do { 7200946e70aSDimitry Andric P++; 7210946e70aSDimitry Andric IsDelim = isDelimiter(Stack[P - 1]); 7220946e70aSDimitry Andric } while (P < SS && IsDelim); 7230946e70aSDimitry Andric assert(!IsDelim); 7240946e70aSDimitry Andric return P; 7250946e70aSDimitry Andric } 7260946e70aSDimitry Andric 7270946e70aSDimitry Andric // Move the stack iterator down by one. 7280946e70aSDimitry Andric unsigned DataFlowGraph::DefStack::nextDown(unsigned P) const { 7290946e70aSDimitry Andric // Get the preceding valid position before P (skipping all delimiters). 7300946e70aSDimitry Andric // The input position P does not have to point to a non-delimiter. 7310946e70aSDimitry Andric assert(P > 0 && P <= Stack.size()); 7320946e70aSDimitry Andric bool IsDelim = isDelimiter(Stack[P - 1]); 7330946e70aSDimitry Andric do { 7340946e70aSDimitry Andric if (--P == 0) 7350946e70aSDimitry Andric break; 7360946e70aSDimitry Andric IsDelim = isDelimiter(Stack[P - 1]); 7370946e70aSDimitry Andric } while (P > 0 && IsDelim); 7380946e70aSDimitry Andric assert(!IsDelim); 7390946e70aSDimitry Andric return P; 7400946e70aSDimitry Andric } 7410946e70aSDimitry Andric 7420946e70aSDimitry Andric // Register information. 7430946e70aSDimitry Andric 74406c3fb27SDimitry Andric RegisterAggr DataFlowGraph::getLandingPadLiveIns() const { 74506c3fb27SDimitry Andric RegisterAggr LR(getPRI()); 7460946e70aSDimitry Andric const Function &F = MF.getFunction(); 74706c3fb27SDimitry Andric const Constant *PF = F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr; 7480946e70aSDimitry Andric const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering(); 7490946e70aSDimitry Andric if (RegisterId R = TLI.getExceptionPointerRegister(PF)) 7500946e70aSDimitry Andric LR.insert(RegisterRef(R)); 7510946e70aSDimitry Andric if (!isFuncletEHPersonality(classifyEHPersonality(PF))) { 7520946e70aSDimitry Andric if (RegisterId R = TLI.getExceptionSelectorRegister(PF)) 7530946e70aSDimitry Andric LR.insert(RegisterRef(R)); 7540946e70aSDimitry Andric } 7550946e70aSDimitry Andric return LR; 7560946e70aSDimitry Andric } 7570946e70aSDimitry Andric 7580946e70aSDimitry Andric // Node management functions. 7590946e70aSDimitry Andric 7600946e70aSDimitry Andric // Get the pointer to the node with the id N. 7610946e70aSDimitry Andric NodeBase *DataFlowGraph::ptr(NodeId N) const { 7620946e70aSDimitry Andric if (N == 0) 7630946e70aSDimitry Andric return nullptr; 7640946e70aSDimitry Andric return Memory.ptr(N); 7650946e70aSDimitry Andric } 7660946e70aSDimitry Andric 7670946e70aSDimitry Andric // Get the id of the node at the address P. 7680946e70aSDimitry Andric NodeId DataFlowGraph::id(const NodeBase *P) const { 7690946e70aSDimitry Andric if (P == nullptr) 7700946e70aSDimitry Andric return 0; 7710946e70aSDimitry Andric return Memory.id(P); 7720946e70aSDimitry Andric } 7730946e70aSDimitry Andric 7740946e70aSDimitry Andric // Allocate a new node and set the attributes to Attrs. 77506c3fb27SDimitry Andric Node DataFlowGraph::newNode(uint16_t Attrs) { 77606c3fb27SDimitry Andric Node P = Memory.New(); 7770946e70aSDimitry Andric P.Addr->init(); 7780946e70aSDimitry Andric P.Addr->setAttrs(Attrs); 7790946e70aSDimitry Andric return P; 7800946e70aSDimitry Andric } 7810946e70aSDimitry Andric 7820946e70aSDimitry Andric // Make a copy of the given node B, except for the data-flow links, which 7830946e70aSDimitry Andric // are set to 0. 78406c3fb27SDimitry Andric Node DataFlowGraph::cloneNode(const Node B) { 78506c3fb27SDimitry Andric Node NA = newNode(0); 7860946e70aSDimitry Andric memcpy(NA.Addr, B.Addr, sizeof(NodeBase)); 7870946e70aSDimitry Andric // Ref nodes need to have the data-flow links reset. 7880946e70aSDimitry Andric if (NA.Addr->getType() == NodeAttrs::Ref) { 78906c3fb27SDimitry Andric Ref RA = NA; 7900946e70aSDimitry Andric RA.Addr->setReachingDef(0); 7910946e70aSDimitry Andric RA.Addr->setSibling(0); 7920946e70aSDimitry Andric if (NA.Addr->getKind() == NodeAttrs::Def) { 79306c3fb27SDimitry Andric Def DA = NA; 7940946e70aSDimitry Andric DA.Addr->setReachedDef(0); 7950946e70aSDimitry Andric DA.Addr->setReachedUse(0); 7960946e70aSDimitry Andric } 7970946e70aSDimitry Andric } 7980946e70aSDimitry Andric return NA; 7990946e70aSDimitry Andric } 8000946e70aSDimitry Andric 8010946e70aSDimitry Andric // Allocation routines for specific node types/kinds. 8020946e70aSDimitry Andric 80306c3fb27SDimitry Andric Use DataFlowGraph::newUse(Instr Owner, MachineOperand &Op, uint16_t Flags) { 80406c3fb27SDimitry Andric Use UA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags); 8050946e70aSDimitry Andric UA.Addr->setRegRef(&Op, *this); 8060946e70aSDimitry Andric return UA; 8070946e70aSDimitry Andric } 8080946e70aSDimitry Andric 80906c3fb27SDimitry Andric PhiUse DataFlowGraph::newPhiUse(Phi Owner, RegisterRef RR, Block PredB, 81006c3fb27SDimitry Andric uint16_t Flags) { 81106c3fb27SDimitry Andric PhiUse PUA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags); 8120946e70aSDimitry Andric assert(Flags & NodeAttrs::PhiRef); 8130946e70aSDimitry Andric PUA.Addr->setRegRef(RR, *this); 8140946e70aSDimitry Andric PUA.Addr->setPredecessor(PredB.Id); 8150946e70aSDimitry Andric return PUA; 8160946e70aSDimitry Andric } 8170946e70aSDimitry Andric 81806c3fb27SDimitry Andric Def DataFlowGraph::newDef(Instr Owner, MachineOperand &Op, uint16_t Flags) { 81906c3fb27SDimitry Andric Def DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags); 8200946e70aSDimitry Andric DA.Addr->setRegRef(&Op, *this); 8210946e70aSDimitry Andric return DA; 8220946e70aSDimitry Andric } 8230946e70aSDimitry Andric 82406c3fb27SDimitry Andric Def DataFlowGraph::newDef(Instr Owner, RegisterRef RR, uint16_t Flags) { 82506c3fb27SDimitry Andric Def DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags); 8260946e70aSDimitry Andric assert(Flags & NodeAttrs::PhiRef); 8270946e70aSDimitry Andric DA.Addr->setRegRef(RR, *this); 8280946e70aSDimitry Andric return DA; 8290946e70aSDimitry Andric } 8300946e70aSDimitry Andric 83106c3fb27SDimitry Andric Phi DataFlowGraph::newPhi(Block Owner) { 83206c3fb27SDimitry Andric Phi PA = newNode(NodeAttrs::Code | NodeAttrs::Phi); 8330946e70aSDimitry Andric Owner.Addr->addPhi(PA, *this); 8340946e70aSDimitry Andric return PA; 8350946e70aSDimitry Andric } 8360946e70aSDimitry Andric 83706c3fb27SDimitry Andric Stmt DataFlowGraph::newStmt(Block Owner, MachineInstr *MI) { 83806c3fb27SDimitry Andric Stmt SA = newNode(NodeAttrs::Code | NodeAttrs::Stmt); 8390946e70aSDimitry Andric SA.Addr->setCode(MI); 8400946e70aSDimitry Andric Owner.Addr->addMember(SA, *this); 8410946e70aSDimitry Andric return SA; 8420946e70aSDimitry Andric } 8430946e70aSDimitry Andric 84406c3fb27SDimitry Andric Block DataFlowGraph::newBlock(Func Owner, MachineBasicBlock *BB) { 84506c3fb27SDimitry Andric Block BA = newNode(NodeAttrs::Code | NodeAttrs::Block); 8460946e70aSDimitry Andric BA.Addr->setCode(BB); 8470946e70aSDimitry Andric Owner.Addr->addMember(BA, *this); 8480946e70aSDimitry Andric return BA; 8490946e70aSDimitry Andric } 8500946e70aSDimitry Andric 85106c3fb27SDimitry Andric Func DataFlowGraph::newFunc(MachineFunction *MF) { 85206c3fb27SDimitry Andric Func FA = newNode(NodeAttrs::Code | NodeAttrs::Func); 8530946e70aSDimitry Andric FA.Addr->setCode(MF); 8540946e70aSDimitry Andric return FA; 8550946e70aSDimitry Andric } 8560946e70aSDimitry Andric 8570946e70aSDimitry Andric // Build the data flow graph. 85806c3fb27SDimitry Andric void DataFlowGraph::build(const Config &config) { 8590946e70aSDimitry Andric reset(); 86006c3fb27SDimitry Andric BuildCfg = config; 86106c3fb27SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 86206c3fb27SDimitry Andric ReservedRegs = MRI.getReservedRegs(); 86306c3fb27SDimitry Andric bool SkipReserved = BuildCfg.Options & BuildOptions::OmitReserved; 86406c3fb27SDimitry Andric 86506c3fb27SDimitry Andric auto Insert = [](auto &Set, auto &&Range) { 86606c3fb27SDimitry Andric Set.insert(Range.begin(), Range.end()); 86706c3fb27SDimitry Andric }; 86806c3fb27SDimitry Andric 86906c3fb27SDimitry Andric if (BuildCfg.TrackRegs.empty()) { 87006c3fb27SDimitry Andric std::set<RegisterId> BaseSet; 87106c3fb27SDimitry Andric if (BuildCfg.Classes.empty()) { 87206c3fb27SDimitry Andric // Insert every register. 873*0fca6ea1SDimitry Andric for (unsigned R = 1, E = getPRI().getTRI().getNumRegs(); R != E; ++R) 87406c3fb27SDimitry Andric BaseSet.insert(R); 87506c3fb27SDimitry Andric } else { 87606c3fb27SDimitry Andric for (const TargetRegisterClass *RC : BuildCfg.Classes) { 87706c3fb27SDimitry Andric for (MCPhysReg R : *RC) 87806c3fb27SDimitry Andric BaseSet.insert(R); 87906c3fb27SDimitry Andric } 88006c3fb27SDimitry Andric } 88106c3fb27SDimitry Andric for (RegisterId R : BaseSet) { 88206c3fb27SDimitry Andric if (SkipReserved && ReservedRegs[R]) 88306c3fb27SDimitry Andric continue; 88406c3fb27SDimitry Andric Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R))); 88506c3fb27SDimitry Andric } 88606c3fb27SDimitry Andric } else { 88706c3fb27SDimitry Andric // Track set in Config overrides everything. 88806c3fb27SDimitry Andric for (unsigned R : BuildCfg.TrackRegs) { 88906c3fb27SDimitry Andric if (SkipReserved && ReservedRegs[R]) 89006c3fb27SDimitry Andric continue; 89106c3fb27SDimitry Andric Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R))); 89206c3fb27SDimitry Andric } 89306c3fb27SDimitry Andric } 89406c3fb27SDimitry Andric 89506c3fb27SDimitry Andric TheFunc = newFunc(&MF); 8960946e70aSDimitry Andric 8970946e70aSDimitry Andric if (MF.empty()) 8980946e70aSDimitry Andric return; 8990946e70aSDimitry Andric 9000946e70aSDimitry Andric for (MachineBasicBlock &B : MF) { 90106c3fb27SDimitry Andric Block BA = newBlock(TheFunc, &B); 9020946e70aSDimitry Andric BlockNodes.insert(std::make_pair(&B, BA)); 9030946e70aSDimitry Andric for (MachineInstr &I : B) { 9040946e70aSDimitry Andric if (I.isDebugInstr()) 9050946e70aSDimitry Andric continue; 9060946e70aSDimitry Andric buildStmt(BA, I); 9070946e70aSDimitry Andric } 9080946e70aSDimitry Andric } 9090946e70aSDimitry Andric 91006c3fb27SDimitry Andric Block EA = TheFunc.Addr->getEntryBlock(*this); 91106c3fb27SDimitry Andric NodeList Blocks = TheFunc.Addr->members(*this); 9120946e70aSDimitry Andric 9130946e70aSDimitry Andric // Collect function live-ins and entry block live-ins. 9140946e70aSDimitry Andric MachineBasicBlock &EntryB = *EA.Addr->getCode(); 9150946e70aSDimitry Andric assert(EntryB.pred_empty() && "Function entry block has predecessors"); 9160946e70aSDimitry Andric for (std::pair<unsigned, unsigned> P : MRI.liveins()) 9170946e70aSDimitry Andric LiveIns.insert(RegisterRef(P.first)); 9180946e70aSDimitry Andric if (MRI.tracksLiveness()) { 9190946e70aSDimitry Andric for (auto I : EntryB.liveins()) 9200946e70aSDimitry Andric LiveIns.insert(RegisterRef(I.PhysReg, I.LaneMask)); 9210946e70aSDimitry Andric } 9220946e70aSDimitry Andric 9230946e70aSDimitry Andric // Add function-entry phi nodes for the live-in registers. 92406c3fb27SDimitry Andric for (RegisterRef RR : LiveIns.refs()) { 92506c3fb27SDimitry Andric if (RR.isReg() && !isTracked(RR)) // isReg is likely guaranteed 92606c3fb27SDimitry Andric continue; 92706c3fb27SDimitry Andric Phi PA = newPhi(EA); 9280946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; 92906c3fb27SDimitry Andric Def DA = newDef(PA, RR, PhiFlags); 9300946e70aSDimitry Andric PA.Addr->addMember(DA, *this); 9310946e70aSDimitry Andric } 9320946e70aSDimitry Andric 9330946e70aSDimitry Andric // Add phis for landing pads. 9340946e70aSDimitry Andric // Landing pads, unlike usual backs blocks, are not entered through 9350946e70aSDimitry Andric // branches in the program, or fall-throughs from other blocks. They 9360946e70aSDimitry Andric // are entered from the exception handling runtime and target's ABI 9370946e70aSDimitry Andric // may define certain registers as defined on entry to such a block. 93806c3fb27SDimitry Andric RegisterAggr EHRegs = getLandingPadLiveIns(); 9390946e70aSDimitry Andric if (!EHRegs.empty()) { 94006c3fb27SDimitry Andric for (Block BA : Blocks) { 9410946e70aSDimitry Andric const MachineBasicBlock &B = *BA.Addr->getCode(); 9420946e70aSDimitry Andric if (!B.isEHPad()) 9430946e70aSDimitry Andric continue; 9440946e70aSDimitry Andric 9450946e70aSDimitry Andric // Prepare a list of NodeIds of the block's predecessors. 9460946e70aSDimitry Andric NodeList Preds; 9470946e70aSDimitry Andric for (MachineBasicBlock *PB : B.predecessors()) 9480946e70aSDimitry Andric Preds.push_back(findBlock(PB)); 9490946e70aSDimitry Andric 9500946e70aSDimitry Andric // Build phi nodes for each live-in. 95106c3fb27SDimitry Andric for (RegisterRef RR : EHRegs.refs()) { 95206c3fb27SDimitry Andric if (RR.isReg() && !isTracked(RR)) 95306c3fb27SDimitry Andric continue; 95406c3fb27SDimitry Andric Phi PA = newPhi(BA); 9550946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; 9560946e70aSDimitry Andric // Add def: 95706c3fb27SDimitry Andric Def DA = newDef(PA, RR, PhiFlags); 9580946e70aSDimitry Andric PA.Addr->addMember(DA, *this); 9590946e70aSDimitry Andric // Add uses (no reaching defs for phi uses): 96006c3fb27SDimitry Andric for (Block PBA : Preds) { 96106c3fb27SDimitry Andric PhiUse PUA = newPhiUse(PA, RR, PBA); 9620946e70aSDimitry Andric PA.Addr->addMember(PUA, *this); 9630946e70aSDimitry Andric } 9640946e70aSDimitry Andric } 9650946e70aSDimitry Andric } 9660946e70aSDimitry Andric } 9670946e70aSDimitry Andric 9680946e70aSDimitry Andric // Build a map "PhiM" which will contain, for each block, the set 9690946e70aSDimitry Andric // of references that will require phi definitions in that block. 97006c3fb27SDimitry Andric BlockRefsMap PhiM(getPRI()); 97106c3fb27SDimitry Andric for (Block BA : Blocks) 9720946e70aSDimitry Andric recordDefsForDF(PhiM, BA); 97306c3fb27SDimitry Andric for (Block BA : Blocks) 97406c3fb27SDimitry Andric buildPhis(PhiM, BA); 9750946e70aSDimitry Andric 9760946e70aSDimitry Andric // Link all the refs. This will recursively traverse the dominator tree. 9770946e70aSDimitry Andric DefStackMap DM; 9780946e70aSDimitry Andric linkBlockRefs(DM, EA); 9790946e70aSDimitry Andric 9800946e70aSDimitry Andric // Finally, remove all unused phi nodes. 98106c3fb27SDimitry Andric if (!(BuildCfg.Options & BuildOptions::KeepDeadPhis)) 9820946e70aSDimitry Andric removeUnusedPhis(); 9830946e70aSDimitry Andric } 9840946e70aSDimitry Andric 9850946e70aSDimitry Andric RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const { 98606c3fb27SDimitry Andric assert(RegisterRef::isRegId(Reg) || RegisterRef::isMaskId(Reg)); 9870946e70aSDimitry Andric assert(Reg != 0); 9880946e70aSDimitry Andric if (Sub != 0) 9890946e70aSDimitry Andric Reg = TRI.getSubReg(Reg, Sub); 9900946e70aSDimitry Andric return RegisterRef(Reg); 9910946e70aSDimitry Andric } 9920946e70aSDimitry Andric 9930946e70aSDimitry Andric RegisterRef DataFlowGraph::makeRegRef(const MachineOperand &Op) const { 9940946e70aSDimitry Andric assert(Op.isReg() || Op.isRegMask()); 9950946e70aSDimitry Andric if (Op.isReg()) 9960946e70aSDimitry Andric return makeRegRef(Op.getReg(), Op.getSubReg()); 99706c3fb27SDimitry Andric return RegisterRef(getPRI().getRegMaskId(Op.getRegMask()), 99806c3fb27SDimitry Andric LaneBitmask::getAll()); 9990946e70aSDimitry Andric } 10000946e70aSDimitry Andric 10010946e70aSDimitry Andric // For each stack in the map DefM, push the delimiter for block B on it. 10020946e70aSDimitry Andric void DataFlowGraph::markBlock(NodeId B, DefStackMap &DefM) { 10030946e70aSDimitry Andric // Push block delimiters. 1004fe6060f1SDimitry Andric for (auto &P : DefM) 1005fe6060f1SDimitry Andric P.second.start_block(B); 10060946e70aSDimitry Andric } 10070946e70aSDimitry Andric 10080946e70aSDimitry Andric // Remove all definitions coming from block B from each stack in DefM. 10090946e70aSDimitry Andric void DataFlowGraph::releaseBlock(NodeId B, DefStackMap &DefM) { 10100946e70aSDimitry Andric // Pop all defs from this block from the definition stack. Defs that were 10110946e70aSDimitry Andric // added to the map during the traversal of instructions will not have a 10120946e70aSDimitry Andric // delimiter, but for those, the whole stack will be emptied. 1013fe6060f1SDimitry Andric for (auto &P : DefM) 1014fe6060f1SDimitry Andric P.second.clear_block(B); 10150946e70aSDimitry Andric 10160946e70aSDimitry Andric // Finally, remove empty stacks from the map. 10170946e70aSDimitry Andric for (auto I = DefM.begin(), E = DefM.end(), NextI = I; I != E; I = NextI) { 10180946e70aSDimitry Andric NextI = std::next(I); 10190946e70aSDimitry Andric // This preserves the validity of iterators other than I. 10200946e70aSDimitry Andric if (I->second.empty()) 10210946e70aSDimitry Andric DefM.erase(I); 10220946e70aSDimitry Andric } 10230946e70aSDimitry Andric } 10240946e70aSDimitry Andric 10250946e70aSDimitry Andric // Push all definitions from the instruction node IA to an appropriate 10260946e70aSDimitry Andric // stack in DefM. 102706c3fb27SDimitry Andric void DataFlowGraph::pushAllDefs(Instr IA, DefStackMap &DefM) { 10280946e70aSDimitry Andric pushClobbers(IA, DefM); 10290946e70aSDimitry Andric pushDefs(IA, DefM); 10300946e70aSDimitry Andric } 10310946e70aSDimitry Andric 10320946e70aSDimitry Andric // Push all definitions from the instruction node IA to an appropriate 10330946e70aSDimitry Andric // stack in DefM. 103406c3fb27SDimitry Andric void DataFlowGraph::pushClobbers(Instr IA, DefStackMap &DefM) { 10350946e70aSDimitry Andric NodeSet Visited; 10360946e70aSDimitry Andric std::set<RegisterId> Defined; 10370946e70aSDimitry Andric 10380946e70aSDimitry Andric // The important objectives of this function are: 10390946e70aSDimitry Andric // - to be able to handle instructions both while the graph is being 10400946e70aSDimitry Andric // constructed, and after the graph has been constructed, and 10410946e70aSDimitry Andric // - maintain proper ordering of definitions on the stack for each 10420946e70aSDimitry Andric // register reference: 10430946e70aSDimitry Andric // - if there are two or more related defs in IA (i.e. coming from 10440946e70aSDimitry Andric // the same machine operand), then only push one def on the stack, 10450946e70aSDimitry Andric // - if there are multiple unrelated defs of non-overlapping 10460946e70aSDimitry Andric // subregisters of S, then the stack for S will have both (in an 10470946e70aSDimitry Andric // unspecified order), but the order does not matter from the data- 10480946e70aSDimitry Andric // -flow perspective. 10490946e70aSDimitry Andric 105006c3fb27SDimitry Andric for (Def DA : IA.Addr->members_if(IsDef, *this)) { 10510946e70aSDimitry Andric if (Visited.count(DA.Id)) 10520946e70aSDimitry Andric continue; 10530946e70aSDimitry Andric if (!(DA.Addr->getFlags() & NodeAttrs::Clobbering)) 10540946e70aSDimitry Andric continue; 10550946e70aSDimitry Andric 10560946e70aSDimitry Andric NodeList Rel = getRelatedRefs(IA, DA); 105706c3fb27SDimitry Andric Def PDA = Rel.front(); 10580946e70aSDimitry Andric RegisterRef RR = PDA.Addr->getRegRef(*this); 10590946e70aSDimitry Andric 10600946e70aSDimitry Andric // Push the definition on the stack for the register and all aliases. 10610946e70aSDimitry Andric // The def stack traversal in linkNodeUp will check the exact aliasing. 10620946e70aSDimitry Andric DefM[RR.Reg].push(DA); 10630946e70aSDimitry Andric Defined.insert(RR.Reg); 106406c3fb27SDimitry Andric for (RegisterId A : getPRI().getAliasSet(RR.Reg)) { 106506c3fb27SDimitry Andric if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A))) 106606c3fb27SDimitry Andric continue; 10670946e70aSDimitry Andric // Check that we don't push the same def twice. 10680946e70aSDimitry Andric assert(A != RR.Reg); 10690946e70aSDimitry Andric if (!Defined.count(A)) 10700946e70aSDimitry Andric DefM[A].push(DA); 10710946e70aSDimitry Andric } 10720946e70aSDimitry Andric // Mark all the related defs as visited. 107306c3fb27SDimitry Andric for (Node T : Rel) 10740946e70aSDimitry Andric Visited.insert(T.Id); 10750946e70aSDimitry Andric } 10760946e70aSDimitry Andric } 10770946e70aSDimitry Andric 10780946e70aSDimitry Andric // Push all definitions from the instruction node IA to an appropriate 10790946e70aSDimitry Andric // stack in DefM. 108006c3fb27SDimitry Andric void DataFlowGraph::pushDefs(Instr IA, DefStackMap &DefM) { 10810946e70aSDimitry Andric NodeSet Visited; 10820946e70aSDimitry Andric #ifndef NDEBUG 10830946e70aSDimitry Andric std::set<RegisterId> Defined; 10840946e70aSDimitry Andric #endif 10850946e70aSDimitry Andric 10860946e70aSDimitry Andric // The important objectives of this function are: 10870946e70aSDimitry Andric // - to be able to handle instructions both while the graph is being 10880946e70aSDimitry Andric // constructed, and after the graph has been constructed, and 10890946e70aSDimitry Andric // - maintain proper ordering of definitions on the stack for each 10900946e70aSDimitry Andric // register reference: 10910946e70aSDimitry Andric // - if there are two or more related defs in IA (i.e. coming from 10920946e70aSDimitry Andric // the same machine operand), then only push one def on the stack, 10930946e70aSDimitry Andric // - if there are multiple unrelated defs of non-overlapping 10940946e70aSDimitry Andric // subregisters of S, then the stack for S will have both (in an 10950946e70aSDimitry Andric // unspecified order), but the order does not matter from the data- 10960946e70aSDimitry Andric // -flow perspective. 10970946e70aSDimitry Andric 109806c3fb27SDimitry Andric for (Def DA : IA.Addr->members_if(IsDef, *this)) { 10990946e70aSDimitry Andric if (Visited.count(DA.Id)) 11000946e70aSDimitry Andric continue; 11010946e70aSDimitry Andric if (DA.Addr->getFlags() & NodeAttrs::Clobbering) 11020946e70aSDimitry Andric continue; 11030946e70aSDimitry Andric 11040946e70aSDimitry Andric NodeList Rel = getRelatedRefs(IA, DA); 110506c3fb27SDimitry Andric Def PDA = Rel.front(); 11060946e70aSDimitry Andric RegisterRef RR = PDA.Addr->getRegRef(*this); 11070946e70aSDimitry Andric #ifndef NDEBUG 11080946e70aSDimitry Andric // Assert if the register is defined in two or more unrelated defs. 11090946e70aSDimitry Andric // This could happen if there are two or more def operands defining it. 11100946e70aSDimitry Andric if (!Defined.insert(RR.Reg).second) { 111106c3fb27SDimitry Andric MachineInstr *MI = Stmt(IA).Addr->getCode(); 111206c3fb27SDimitry Andric dbgs() << "Multiple definitions of register: " << Print(RR, *this) 111306c3fb27SDimitry Andric << " in\n " << *MI << "in " << printMBBReference(*MI->getParent()) 111406c3fb27SDimitry Andric << '\n'; 11150946e70aSDimitry Andric llvm_unreachable(nullptr); 11160946e70aSDimitry Andric } 11170946e70aSDimitry Andric #endif 11180946e70aSDimitry Andric // Push the definition on the stack for the register and all aliases. 11190946e70aSDimitry Andric // The def stack traversal in linkNodeUp will check the exact aliasing. 11200946e70aSDimitry Andric DefM[RR.Reg].push(DA); 112106c3fb27SDimitry Andric for (RegisterId A : getPRI().getAliasSet(RR.Reg)) { 112206c3fb27SDimitry Andric if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A))) 112306c3fb27SDimitry Andric continue; 11240946e70aSDimitry Andric // Check that we don't push the same def twice. 11250946e70aSDimitry Andric assert(A != RR.Reg); 11260946e70aSDimitry Andric DefM[A].push(DA); 11270946e70aSDimitry Andric } 11280946e70aSDimitry Andric // Mark all the related defs as visited. 112906c3fb27SDimitry Andric for (Node T : Rel) 11300946e70aSDimitry Andric Visited.insert(T.Id); 11310946e70aSDimitry Andric } 11320946e70aSDimitry Andric } 11330946e70aSDimitry Andric 11340946e70aSDimitry Andric // Return the list of all reference nodes related to RA, including RA itself. 11350946e70aSDimitry Andric // See "getNextRelated" for the meaning of a "related reference". 113606c3fb27SDimitry Andric NodeList DataFlowGraph::getRelatedRefs(Instr IA, Ref RA) const { 11370946e70aSDimitry Andric assert(IA.Id != 0 && RA.Id != 0); 11380946e70aSDimitry Andric 11390946e70aSDimitry Andric NodeList Refs; 11400946e70aSDimitry Andric NodeId Start = RA.Id; 11410946e70aSDimitry Andric do { 11420946e70aSDimitry Andric Refs.push_back(RA); 11430946e70aSDimitry Andric RA = getNextRelated(IA, RA); 11440946e70aSDimitry Andric } while (RA.Id != 0 && RA.Id != Start); 11450946e70aSDimitry Andric return Refs; 11460946e70aSDimitry Andric } 11470946e70aSDimitry Andric 11480946e70aSDimitry Andric // Clear all information in the graph. 11490946e70aSDimitry Andric void DataFlowGraph::reset() { 11500946e70aSDimitry Andric Memory.clear(); 11510946e70aSDimitry Andric BlockNodes.clear(); 115206c3fb27SDimitry Andric TrackedUnits.clear(); 115306c3fb27SDimitry Andric ReservedRegs.clear(); 115406c3fb27SDimitry Andric TheFunc = Func(); 11550946e70aSDimitry Andric } 11560946e70aSDimitry Andric 11570946e70aSDimitry Andric // Return the next reference node in the instruction node IA that is related 11580946e70aSDimitry Andric // to RA. Conceptually, two reference nodes are related if they refer to the 11590946e70aSDimitry Andric // same instance of a register access, but differ in flags or other minor 11600946e70aSDimitry Andric // characteristics. Specific examples of related nodes are shadow reference 11610946e70aSDimitry Andric // nodes. 11620946e70aSDimitry Andric // Return the equivalent of nullptr if there are no more related references. 116306c3fb27SDimitry Andric Ref DataFlowGraph::getNextRelated(Instr IA, Ref RA) const { 11640946e70aSDimitry Andric assert(IA.Id != 0 && RA.Id != 0); 11650946e70aSDimitry Andric 116606c3fb27SDimitry Andric auto IsRelated = [this, RA](Ref TA) -> bool { 11670946e70aSDimitry Andric if (TA.Addr->getKind() != RA.Addr->getKind()) 11680946e70aSDimitry Andric return false; 116906c3fb27SDimitry Andric if (!getPRI().equal_to(TA.Addr->getRegRef(*this), 117006c3fb27SDimitry Andric RA.Addr->getRegRef(*this))) { 11710946e70aSDimitry Andric return false; 117206c3fb27SDimitry Andric } 11730946e70aSDimitry Andric return true; 11740946e70aSDimitry Andric }; 117506c3fb27SDimitry Andric 117606c3fb27SDimitry Andric RegisterRef RR = RA.Addr->getRegRef(*this); 117706c3fb27SDimitry Andric if (IA.Addr->getKind() == NodeAttrs::Stmt) { 117806c3fb27SDimitry Andric auto Cond = [&IsRelated, RA](Ref TA) -> bool { 117906c3fb27SDimitry Andric return IsRelated(TA) && &RA.Addr->getOp() == &TA.Addr->getOp(); 11800946e70aSDimitry Andric }; 118106c3fb27SDimitry Andric return RA.Addr->getNextRef(RR, Cond, true, *this); 118206c3fb27SDimitry Andric } 118306c3fb27SDimitry Andric 118406c3fb27SDimitry Andric assert(IA.Addr->getKind() == NodeAttrs::Phi); 118506c3fb27SDimitry Andric auto Cond = [&IsRelated, RA](Ref TA) -> bool { 118606c3fb27SDimitry Andric if (!IsRelated(TA)) 11870946e70aSDimitry Andric return false; 11880946e70aSDimitry Andric if (TA.Addr->getKind() != NodeAttrs::Use) 11890946e70aSDimitry Andric return true; 11900946e70aSDimitry Andric // For phi uses, compare predecessor blocks. 119106c3fb27SDimitry Andric return PhiUse(TA).Addr->getPredecessor() == 119206c3fb27SDimitry Andric PhiUse(RA).Addr->getPredecessor(); 11930946e70aSDimitry Andric }; 119406c3fb27SDimitry Andric return RA.Addr->getNextRef(RR, Cond, true, *this); 11950946e70aSDimitry Andric } 11960946e70aSDimitry Andric 11970946e70aSDimitry Andric // Find the next node related to RA in IA that satisfies condition P. 11980946e70aSDimitry Andric // If such a node was found, return a pair where the second element is the 11990946e70aSDimitry Andric // located node. If such a node does not exist, return a pair where the 12000946e70aSDimitry Andric // first element is the element after which such a node should be inserted, 12010946e70aSDimitry Andric // and the second element is a null-address. 12020946e70aSDimitry Andric template <typename Predicate> 120306c3fb27SDimitry Andric std::pair<Ref, Ref> DataFlowGraph::locateNextRef(Instr IA, Ref RA, 12040946e70aSDimitry Andric Predicate P) const { 12050946e70aSDimitry Andric assert(IA.Id != 0 && RA.Id != 0); 12060946e70aSDimitry Andric 120706c3fb27SDimitry Andric Ref NA; 12080946e70aSDimitry Andric NodeId Start = RA.Id; 12090946e70aSDimitry Andric while (true) { 12100946e70aSDimitry Andric NA = getNextRelated(IA, RA); 12110946e70aSDimitry Andric if (NA.Id == 0 || NA.Id == Start) 12120946e70aSDimitry Andric break; 12130946e70aSDimitry Andric if (P(NA)) 12140946e70aSDimitry Andric break; 12150946e70aSDimitry Andric RA = NA; 12160946e70aSDimitry Andric } 12170946e70aSDimitry Andric 12180946e70aSDimitry Andric if (NA.Id != 0 && NA.Id != Start) 12190946e70aSDimitry Andric return std::make_pair(RA, NA); 122006c3fb27SDimitry Andric return std::make_pair(RA, Ref()); 12210946e70aSDimitry Andric } 12220946e70aSDimitry Andric 12230946e70aSDimitry Andric // Get the next shadow node in IA corresponding to RA, and optionally create 12240946e70aSDimitry Andric // such a node if it does not exist. 122506c3fb27SDimitry Andric Ref DataFlowGraph::getNextShadow(Instr IA, Ref RA, bool Create) { 12260946e70aSDimitry Andric assert(IA.Id != 0 && RA.Id != 0); 12270946e70aSDimitry Andric 12280946e70aSDimitry Andric uint16_t Flags = RA.Addr->getFlags() | NodeAttrs::Shadow; 122906c3fb27SDimitry Andric auto IsShadow = [Flags](Ref TA) -> bool { 12300946e70aSDimitry Andric return TA.Addr->getFlags() == Flags; 12310946e70aSDimitry Andric }; 12320946e70aSDimitry Andric auto Loc = locateNextRef(IA, RA, IsShadow); 12330946e70aSDimitry Andric if (Loc.second.Id != 0 || !Create) 12340946e70aSDimitry Andric return Loc.second; 12350946e70aSDimitry Andric 12360946e70aSDimitry Andric // Create a copy of RA and mark is as shadow. 123706c3fb27SDimitry Andric Ref NA = cloneNode(RA); 12380946e70aSDimitry Andric NA.Addr->setFlags(Flags | NodeAttrs::Shadow); 12390946e70aSDimitry Andric IA.Addr->addMemberAfter(Loc.first, NA, *this); 12400946e70aSDimitry Andric return NA; 12410946e70aSDimitry Andric } 12420946e70aSDimitry Andric 12430946e70aSDimitry Andric // Create a new statement node in the block node BA that corresponds to 12440946e70aSDimitry Andric // the machine instruction MI. 124506c3fb27SDimitry Andric void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) { 124606c3fb27SDimitry Andric Stmt SA = newStmt(BA, &In); 12470946e70aSDimitry Andric 12480946e70aSDimitry Andric auto isCall = [](const MachineInstr &In) -> bool { 12490946e70aSDimitry Andric if (In.isCall()) 12500946e70aSDimitry Andric return true; 12510946e70aSDimitry Andric // Is tail call? 12520946e70aSDimitry Andric if (In.isBranch()) { 12530946e70aSDimitry Andric for (const MachineOperand &Op : In.operands()) 12540946e70aSDimitry Andric if (Op.isGlobal() || Op.isSymbol()) 12550946e70aSDimitry Andric return true; 12560946e70aSDimitry Andric // Assume indirect branches are calls. This is for the purpose of 12570946e70aSDimitry Andric // keeping implicit operands, and so it won't hurt on intra-function 12580946e70aSDimitry Andric // indirect branches. 12590946e70aSDimitry Andric if (In.isIndirectBranch()) 12600946e70aSDimitry Andric return true; 12610946e70aSDimitry Andric } 12620946e70aSDimitry Andric return false; 12630946e70aSDimitry Andric }; 12640946e70aSDimitry Andric 12650946e70aSDimitry Andric auto isDefUndef = [this](const MachineInstr &In, RegisterRef DR) -> bool { 12660946e70aSDimitry Andric // This instruction defines DR. Check if there is a use operand that 12670946e70aSDimitry Andric // would make DR live on entry to the instruction. 126806c3fb27SDimitry Andric for (const MachineOperand &Op : In.all_uses()) { 126906c3fb27SDimitry Andric if (Op.getReg() == 0 || Op.isUndef()) 12700946e70aSDimitry Andric continue; 12710946e70aSDimitry Andric RegisterRef UR = makeRegRef(Op); 127206c3fb27SDimitry Andric if (getPRI().alias(DR, UR)) 12730946e70aSDimitry Andric return false; 12740946e70aSDimitry Andric } 12750946e70aSDimitry Andric return true; 12760946e70aSDimitry Andric }; 12770946e70aSDimitry Andric 12780946e70aSDimitry Andric bool IsCall = isCall(In); 12790946e70aSDimitry Andric unsigned NumOps = In.getNumOperands(); 12800946e70aSDimitry Andric 12810946e70aSDimitry Andric // Avoid duplicate implicit defs. This will not detect cases of implicit 12820946e70aSDimitry Andric // defs that define registers that overlap, but it is not clear how to 12830946e70aSDimitry Andric // interpret that in the absence of explicit defs. Overlapping explicit 12840946e70aSDimitry Andric // defs are likely illegal already. 12850946e70aSDimitry Andric BitVector DoneDefs(TRI.getNumRegs()); 12860946e70aSDimitry Andric // Process explicit defs first. 12870946e70aSDimitry Andric for (unsigned OpN = 0; OpN < NumOps; ++OpN) { 12880946e70aSDimitry Andric MachineOperand &Op = In.getOperand(OpN); 12890946e70aSDimitry Andric if (!Op.isReg() || !Op.isDef() || Op.isImplicit()) 12900946e70aSDimitry Andric continue; 12910946e70aSDimitry Andric Register R = Op.getReg(); 129206c3fb27SDimitry Andric if (!R || !R.isPhysical() || !isTracked(RegisterRef(R))) 12930946e70aSDimitry Andric continue; 12940946e70aSDimitry Andric uint16_t Flags = NodeAttrs::None; 12950946e70aSDimitry Andric if (TOI.isPreserving(In, OpN)) { 12960946e70aSDimitry Andric Flags |= NodeAttrs::Preserving; 12970946e70aSDimitry Andric // If the def is preserving, check if it is also undefined. 12980946e70aSDimitry Andric if (isDefUndef(In, makeRegRef(Op))) 12990946e70aSDimitry Andric Flags |= NodeAttrs::Undef; 13000946e70aSDimitry Andric } 13010946e70aSDimitry Andric if (TOI.isClobbering(In, OpN)) 13020946e70aSDimitry Andric Flags |= NodeAttrs::Clobbering; 13030946e70aSDimitry Andric if (TOI.isFixedReg(In, OpN)) 13040946e70aSDimitry Andric Flags |= NodeAttrs::Fixed; 13050946e70aSDimitry Andric if (IsCall && Op.isDead()) 13060946e70aSDimitry Andric Flags |= NodeAttrs::Dead; 130706c3fb27SDimitry Andric Def DA = newDef(SA, Op, Flags); 13080946e70aSDimitry Andric SA.Addr->addMember(DA, *this); 13090946e70aSDimitry Andric assert(!DoneDefs.test(R)); 13100946e70aSDimitry Andric DoneDefs.set(R); 13110946e70aSDimitry Andric } 13120946e70aSDimitry Andric 13130946e70aSDimitry Andric // Process reg-masks (as clobbers). 13140946e70aSDimitry Andric BitVector DoneClobbers(TRI.getNumRegs()); 13150946e70aSDimitry Andric for (unsigned OpN = 0; OpN < NumOps; ++OpN) { 13160946e70aSDimitry Andric MachineOperand &Op = In.getOperand(OpN); 13170946e70aSDimitry Andric if (!Op.isRegMask()) 13180946e70aSDimitry Andric continue; 131906c3fb27SDimitry Andric uint16_t Flags = NodeAttrs::Clobbering | NodeAttrs::Fixed | NodeAttrs::Dead; 132006c3fb27SDimitry Andric Def DA = newDef(SA, Op, Flags); 13210946e70aSDimitry Andric SA.Addr->addMember(DA, *this); 13220946e70aSDimitry Andric // Record all clobbered registers in DoneDefs. 13230946e70aSDimitry Andric const uint32_t *RM = Op.getRegMask(); 132406c3fb27SDimitry Andric for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) { 132506c3fb27SDimitry Andric if (!isTracked(RegisterRef(i))) 132606c3fb27SDimitry Andric continue; 13270946e70aSDimitry Andric if (!(RM[i / 32] & (1u << (i % 32)))) 13280946e70aSDimitry Andric DoneClobbers.set(i); 13290946e70aSDimitry Andric } 133006c3fb27SDimitry Andric } 13310946e70aSDimitry Andric 13320946e70aSDimitry Andric // Process implicit defs, skipping those that have already been added 13330946e70aSDimitry Andric // as explicit. 13340946e70aSDimitry Andric for (unsigned OpN = 0; OpN < NumOps; ++OpN) { 13350946e70aSDimitry Andric MachineOperand &Op = In.getOperand(OpN); 13360946e70aSDimitry Andric if (!Op.isReg() || !Op.isDef() || !Op.isImplicit()) 13370946e70aSDimitry Andric continue; 13380946e70aSDimitry Andric Register R = Op.getReg(); 133906c3fb27SDimitry Andric if (!R || !R.isPhysical() || !isTracked(RegisterRef(R)) || DoneDefs.test(R)) 13400946e70aSDimitry Andric continue; 13410946e70aSDimitry Andric RegisterRef RR = makeRegRef(Op); 13420946e70aSDimitry Andric uint16_t Flags = NodeAttrs::None; 13430946e70aSDimitry Andric if (TOI.isPreserving(In, OpN)) { 13440946e70aSDimitry Andric Flags |= NodeAttrs::Preserving; 13450946e70aSDimitry Andric // If the def is preserving, check if it is also undefined. 13460946e70aSDimitry Andric if (isDefUndef(In, RR)) 13470946e70aSDimitry Andric Flags |= NodeAttrs::Undef; 13480946e70aSDimitry Andric } 13490946e70aSDimitry Andric if (TOI.isClobbering(In, OpN)) 13500946e70aSDimitry Andric Flags |= NodeAttrs::Clobbering; 13510946e70aSDimitry Andric if (TOI.isFixedReg(In, OpN)) 13520946e70aSDimitry Andric Flags |= NodeAttrs::Fixed; 13530946e70aSDimitry Andric if (IsCall && Op.isDead()) { 13540946e70aSDimitry Andric if (DoneClobbers.test(R)) 13550946e70aSDimitry Andric continue; 13560946e70aSDimitry Andric Flags |= NodeAttrs::Dead; 13570946e70aSDimitry Andric } 135806c3fb27SDimitry Andric Def DA = newDef(SA, Op, Flags); 13590946e70aSDimitry Andric SA.Addr->addMember(DA, *this); 13600946e70aSDimitry Andric DoneDefs.set(R); 13610946e70aSDimitry Andric } 13620946e70aSDimitry Andric 13630946e70aSDimitry Andric for (unsigned OpN = 0; OpN < NumOps; ++OpN) { 13640946e70aSDimitry Andric MachineOperand &Op = In.getOperand(OpN); 13650946e70aSDimitry Andric if (!Op.isReg() || !Op.isUse()) 13660946e70aSDimitry Andric continue; 13670946e70aSDimitry Andric Register R = Op.getReg(); 136806c3fb27SDimitry Andric if (!R || !R.isPhysical() || !isTracked(RegisterRef(R))) 13690946e70aSDimitry Andric continue; 13700946e70aSDimitry Andric uint16_t Flags = NodeAttrs::None; 13710946e70aSDimitry Andric if (Op.isUndef()) 13720946e70aSDimitry Andric Flags |= NodeAttrs::Undef; 13730946e70aSDimitry Andric if (TOI.isFixedReg(In, OpN)) 13740946e70aSDimitry Andric Flags |= NodeAttrs::Fixed; 137506c3fb27SDimitry Andric Use UA = newUse(SA, Op, Flags); 13760946e70aSDimitry Andric SA.Addr->addMember(UA, *this); 13770946e70aSDimitry Andric } 13780946e70aSDimitry Andric } 13790946e70aSDimitry Andric 13800946e70aSDimitry Andric // Scan all defs in the block node BA and record in PhiM the locations of 13810946e70aSDimitry Andric // phi nodes corresponding to these defs. 138206c3fb27SDimitry Andric void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, Block BA) { 13830946e70aSDimitry Andric // Check all defs from block BA and record them in each block in BA's 13840946e70aSDimitry Andric // iterated dominance frontier. This information will later be used to 13850946e70aSDimitry Andric // create phi nodes. 13860946e70aSDimitry Andric MachineBasicBlock *BB = BA.Addr->getCode(); 13870946e70aSDimitry Andric assert(BB); 13880946e70aSDimitry Andric auto DFLoc = MDF.find(BB); 13890946e70aSDimitry Andric if (DFLoc == MDF.end() || DFLoc->second.empty()) 13900946e70aSDimitry Andric return; 13910946e70aSDimitry Andric 13920946e70aSDimitry Andric // Traverse all instructions in the block and collect the set of all 13930946e70aSDimitry Andric // defined references. For each reference there will be a phi created 13940946e70aSDimitry Andric // in the block's iterated dominance frontier. 13950946e70aSDimitry Andric // This is done to make sure that each defined reference gets only one 13960946e70aSDimitry Andric // phi node, even if it is defined multiple times. 139706c3fb27SDimitry Andric RegisterAggr Defs(getPRI()); 139806c3fb27SDimitry Andric for (Instr IA : BA.Addr->members(*this)) { 139906c3fb27SDimitry Andric for (Ref RA : IA.Addr->members_if(IsDef, *this)) { 140006c3fb27SDimitry Andric RegisterRef RR = RA.Addr->getRegRef(*this); 140106c3fb27SDimitry Andric if (RR.isReg() && isTracked(RR)) 140206c3fb27SDimitry Andric Defs.insert(RR); 140306c3fb27SDimitry Andric } 140406c3fb27SDimitry Andric } 14050946e70aSDimitry Andric 14060946e70aSDimitry Andric // Calculate the iterated dominance frontier of BB. 14070946e70aSDimitry Andric const MachineDominanceFrontier::DomSetType &DF = DFLoc->second; 14080946e70aSDimitry Andric SetVector<MachineBasicBlock *> IDF(DF.begin(), DF.end()); 14090946e70aSDimitry Andric for (unsigned i = 0; i < IDF.size(); ++i) { 14100946e70aSDimitry Andric auto F = MDF.find(IDF[i]); 14110946e70aSDimitry Andric if (F != MDF.end()) 14120946e70aSDimitry Andric IDF.insert(F->second.begin(), F->second.end()); 14130946e70aSDimitry Andric } 14140946e70aSDimitry Andric 14150946e70aSDimitry Andric // Finally, add the set of defs to each block in the iterated dominance 14160946e70aSDimitry Andric // frontier. 1417fcaf7f86SDimitry Andric for (auto *DB : IDF) { 141806c3fb27SDimitry Andric Block DBA = findBlock(DB); 141906c3fb27SDimitry Andric PhiM[DBA.Id].insert(Defs); 14200946e70aSDimitry Andric } 14210946e70aSDimitry Andric } 14220946e70aSDimitry Andric 14230946e70aSDimitry Andric // Given the locations of phi nodes in the map PhiM, create the phi nodes 14240946e70aSDimitry Andric // that are located in the block node BA. 142506c3fb27SDimitry Andric void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, Block BA) { 14260946e70aSDimitry Andric // Check if this blocks has any DF defs, i.e. if there are any defs 14270946e70aSDimitry Andric // that this block is in the iterated dominance frontier of. 14280946e70aSDimitry Andric auto HasDF = PhiM.find(BA.Id); 14290946e70aSDimitry Andric if (HasDF == PhiM.end() || HasDF->second.empty()) 14300946e70aSDimitry Andric return; 14310946e70aSDimitry Andric 14320946e70aSDimitry Andric // Prepare a list of NodeIds of the block's predecessors. 14330946e70aSDimitry Andric NodeList Preds; 14340946e70aSDimitry Andric const MachineBasicBlock *MBB = BA.Addr->getCode(); 14350946e70aSDimitry Andric for (MachineBasicBlock *PB : MBB->predecessors()) 14360946e70aSDimitry Andric Preds.push_back(findBlock(PB)); 14370946e70aSDimitry Andric 143806c3fb27SDimitry Andric const RegisterAggr &Defs = PhiM[BA.Id]; 14390946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; 14400946e70aSDimitry Andric 144106c3fb27SDimitry Andric for (RegisterRef RR : Defs.refs()) { 144206c3fb27SDimitry Andric Phi PA = newPhi(BA); 144306c3fb27SDimitry Andric PA.Addr->addMember(newDef(PA, RR, PhiFlags), *this); 144406c3fb27SDimitry Andric 144506c3fb27SDimitry Andric // Add phi uses. 144606c3fb27SDimitry Andric for (Block PBA : Preds) { 144706c3fb27SDimitry Andric PA.Addr->addMember(newPhiUse(PA, RR, PBA), *this); 144806c3fb27SDimitry Andric } 14490946e70aSDimitry Andric } 14500946e70aSDimitry Andric } 14510946e70aSDimitry Andric 14520946e70aSDimitry Andric // Remove any unneeded phi nodes that were created during the build process. 14530946e70aSDimitry Andric void DataFlowGraph::removeUnusedPhis() { 14540946e70aSDimitry Andric // This will remove unused phis, i.e. phis where each def does not reach 14550946e70aSDimitry Andric // any uses or other defs. This will not detect or remove circular phi 14560946e70aSDimitry Andric // chains that are otherwise dead. Unused/dead phis are created during 14570946e70aSDimitry Andric // the build process and this function is intended to remove these cases 14580946e70aSDimitry Andric // that are easily determinable to be unnecessary. 14590946e70aSDimitry Andric 14600946e70aSDimitry Andric SetVector<NodeId> PhiQ; 146106c3fb27SDimitry Andric for (Block BA : TheFunc.Addr->members(*this)) { 14620946e70aSDimitry Andric for (auto P : BA.Addr->members_if(IsPhi, *this)) 14630946e70aSDimitry Andric PhiQ.insert(P.Id); 14640946e70aSDimitry Andric } 14650946e70aSDimitry Andric 14660946e70aSDimitry Andric static auto HasUsedDef = [](NodeList &Ms) -> bool { 146706c3fb27SDimitry Andric for (Node M : Ms) { 14680946e70aSDimitry Andric if (M.Addr->getKind() != NodeAttrs::Def) 14690946e70aSDimitry Andric continue; 147006c3fb27SDimitry Andric Def DA = M; 14710946e70aSDimitry Andric if (DA.Addr->getReachedDef() != 0 || DA.Addr->getReachedUse() != 0) 14720946e70aSDimitry Andric return true; 14730946e70aSDimitry Andric } 14740946e70aSDimitry Andric return false; 14750946e70aSDimitry Andric }; 14760946e70aSDimitry Andric 14770946e70aSDimitry Andric // Any phi, if it is removed, may affect other phis (make them dead). 14780946e70aSDimitry Andric // For each removed phi, collect the potentially affected phis and add 14790946e70aSDimitry Andric // them back to the queue. 14800946e70aSDimitry Andric while (!PhiQ.empty()) { 14810946e70aSDimitry Andric auto PA = addr<PhiNode *>(PhiQ[0]); 14820946e70aSDimitry Andric PhiQ.remove(PA.Id); 14830946e70aSDimitry Andric NodeList Refs = PA.Addr->members(*this); 14840946e70aSDimitry Andric if (HasUsedDef(Refs)) 14850946e70aSDimitry Andric continue; 148606c3fb27SDimitry Andric for (Ref RA : Refs) { 14870946e70aSDimitry Andric if (NodeId RD = RA.Addr->getReachingDef()) { 14880946e70aSDimitry Andric auto RDA = addr<DefNode *>(RD); 148906c3fb27SDimitry Andric Instr OA = RDA.Addr->getOwner(*this); 14900946e70aSDimitry Andric if (IsPhi(OA)) 14910946e70aSDimitry Andric PhiQ.insert(OA.Id); 14920946e70aSDimitry Andric } 14930946e70aSDimitry Andric if (RA.Addr->isDef()) 14940946e70aSDimitry Andric unlinkDef(RA, true); 14950946e70aSDimitry Andric else 14960946e70aSDimitry Andric unlinkUse(RA, true); 14970946e70aSDimitry Andric } 149806c3fb27SDimitry Andric Block BA = PA.Addr->getOwner(*this); 14990946e70aSDimitry Andric BA.Addr->removeMember(PA, *this); 15000946e70aSDimitry Andric } 15010946e70aSDimitry Andric } 15020946e70aSDimitry Andric 15030946e70aSDimitry Andric // For a given reference node TA in an instruction node IA, connect the 15040946e70aSDimitry Andric // reaching def of TA to the appropriate def node. Create any shadow nodes 15050946e70aSDimitry Andric // as appropriate. 15060946e70aSDimitry Andric template <typename T> 150706c3fb27SDimitry Andric void DataFlowGraph::linkRefUp(Instr IA, NodeAddr<T> TA, DefStack &DS) { 15080946e70aSDimitry Andric if (DS.empty()) 15090946e70aSDimitry Andric return; 15100946e70aSDimitry Andric RegisterRef RR = TA.Addr->getRegRef(*this); 15110946e70aSDimitry Andric NodeAddr<T> TAP; 15120946e70aSDimitry Andric 15130946e70aSDimitry Andric // References from the def stack that have been examined so far. 151406c3fb27SDimitry Andric RegisterAggr Defs(getPRI()); 15150946e70aSDimitry Andric 15160946e70aSDimitry Andric for (auto I = DS.top(), E = DS.bottom(); I != E; I.down()) { 15170946e70aSDimitry Andric RegisterRef QR = I->Addr->getRegRef(*this); 15180946e70aSDimitry Andric 15190946e70aSDimitry Andric // Skip all defs that are aliased to any of the defs that we have already 15200946e70aSDimitry Andric // seen. If this completes a cover of RR, stop the stack traversal. 15210946e70aSDimitry Andric bool Alias = Defs.hasAliasOf(QR); 15220946e70aSDimitry Andric bool Cover = Defs.insert(QR).hasCoverOf(RR); 15230946e70aSDimitry Andric if (Alias) { 15240946e70aSDimitry Andric if (Cover) 15250946e70aSDimitry Andric break; 15260946e70aSDimitry Andric continue; 15270946e70aSDimitry Andric } 15280946e70aSDimitry Andric 15290946e70aSDimitry Andric // The reaching def. 153006c3fb27SDimitry Andric Def RDA = *I; 15310946e70aSDimitry Andric 15320946e70aSDimitry Andric // Pick the reached node. 15330946e70aSDimitry Andric if (TAP.Id == 0) { 15340946e70aSDimitry Andric TAP = TA; 15350946e70aSDimitry Andric } else { 15360946e70aSDimitry Andric // Mark the existing ref as "shadow" and create a new shadow. 15370946e70aSDimitry Andric TAP.Addr->setFlags(TAP.Addr->getFlags() | NodeAttrs::Shadow); 15380946e70aSDimitry Andric TAP = getNextShadow(IA, TAP, true); 15390946e70aSDimitry Andric } 15400946e70aSDimitry Andric 15410946e70aSDimitry Andric // Create the link. 15420946e70aSDimitry Andric TAP.Addr->linkToDef(TAP.Id, RDA); 15430946e70aSDimitry Andric 15440946e70aSDimitry Andric if (Cover) 15450946e70aSDimitry Andric break; 15460946e70aSDimitry Andric } 15470946e70aSDimitry Andric } 15480946e70aSDimitry Andric 15490946e70aSDimitry Andric // Create data-flow links for all reference nodes in the statement node SA. 15500946e70aSDimitry Andric template <typename Predicate> 155106c3fb27SDimitry Andric void DataFlowGraph::linkStmtRefs(DefStackMap &DefM, Stmt SA, Predicate P) { 15520946e70aSDimitry Andric #ifndef NDEBUG 155306c3fb27SDimitry Andric RegisterSet Defs(getPRI()); 15540946e70aSDimitry Andric #endif 15550946e70aSDimitry Andric 15560946e70aSDimitry Andric // Link all nodes (upwards in the data-flow) with their reaching defs. 155706c3fb27SDimitry Andric for (Ref RA : SA.Addr->members_if(P, *this)) { 15580946e70aSDimitry Andric uint16_t Kind = RA.Addr->getKind(); 15590946e70aSDimitry Andric assert(Kind == NodeAttrs::Def || Kind == NodeAttrs::Use); 15600946e70aSDimitry Andric RegisterRef RR = RA.Addr->getRegRef(*this); 15610946e70aSDimitry Andric #ifndef NDEBUG 15620946e70aSDimitry Andric // Do not expect multiple defs of the same reference. 15630946e70aSDimitry Andric assert(Kind != NodeAttrs::Def || !Defs.count(RR)); 15640946e70aSDimitry Andric Defs.insert(RR); 15650946e70aSDimitry Andric #endif 15660946e70aSDimitry Andric 15670946e70aSDimitry Andric auto F = DefM.find(RR.Reg); 15680946e70aSDimitry Andric if (F == DefM.end()) 15690946e70aSDimitry Andric continue; 15700946e70aSDimitry Andric DefStack &DS = F->second; 15710946e70aSDimitry Andric if (Kind == NodeAttrs::Use) 15720946e70aSDimitry Andric linkRefUp<UseNode *>(SA, RA, DS); 15730946e70aSDimitry Andric else if (Kind == NodeAttrs::Def) 15740946e70aSDimitry Andric linkRefUp<DefNode *>(SA, RA, DS); 15750946e70aSDimitry Andric else 15760946e70aSDimitry Andric llvm_unreachable("Unexpected node in instruction"); 15770946e70aSDimitry Andric } 15780946e70aSDimitry Andric } 15790946e70aSDimitry Andric 15800946e70aSDimitry Andric // Create data-flow links for all instructions in the block node BA. This 15810946e70aSDimitry Andric // will include updating any phi nodes in BA. 158206c3fb27SDimitry Andric void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, Block BA) { 15830946e70aSDimitry Andric // Push block delimiters. 15840946e70aSDimitry Andric markBlock(BA.Id, DefM); 15850946e70aSDimitry Andric 158606c3fb27SDimitry Andric auto IsClobber = [](Ref RA) -> bool { 15870946e70aSDimitry Andric return IsDef(RA) && (RA.Addr->getFlags() & NodeAttrs::Clobbering); 15880946e70aSDimitry Andric }; 158906c3fb27SDimitry Andric auto IsNoClobber = [](Ref RA) -> bool { 15900946e70aSDimitry Andric return IsDef(RA) && !(RA.Addr->getFlags() & NodeAttrs::Clobbering); 15910946e70aSDimitry Andric }; 15920946e70aSDimitry Andric 15930946e70aSDimitry Andric assert(BA.Addr && "block node address is needed to create a data-flow link"); 15940946e70aSDimitry Andric // For each non-phi instruction in the block, link all the defs and uses 15950946e70aSDimitry Andric // to their reaching defs. For any member of the block (including phis), 15960946e70aSDimitry Andric // push the defs on the corresponding stacks. 159706c3fb27SDimitry Andric for (Instr IA : BA.Addr->members(*this)) { 15980946e70aSDimitry Andric // Ignore phi nodes here. They will be linked part by part from the 15990946e70aSDimitry Andric // predecessors. 16000946e70aSDimitry Andric if (IA.Addr->getKind() == NodeAttrs::Stmt) { 16010946e70aSDimitry Andric linkStmtRefs(DefM, IA, IsUse); 16020946e70aSDimitry Andric linkStmtRefs(DefM, IA, IsClobber); 16030946e70aSDimitry Andric } 16040946e70aSDimitry Andric 16050946e70aSDimitry Andric // Push the definitions on the stack. 16060946e70aSDimitry Andric pushClobbers(IA, DefM); 16070946e70aSDimitry Andric 16080946e70aSDimitry Andric if (IA.Addr->getKind() == NodeAttrs::Stmt) 16090946e70aSDimitry Andric linkStmtRefs(DefM, IA, IsNoClobber); 16100946e70aSDimitry Andric 16110946e70aSDimitry Andric pushDefs(IA, DefM); 16120946e70aSDimitry Andric } 16130946e70aSDimitry Andric 16140946e70aSDimitry Andric // Recursively process all children in the dominator tree. 16150946e70aSDimitry Andric MachineDomTreeNode *N = MDT.getNode(BA.Addr->getCode()); 1616fcaf7f86SDimitry Andric for (auto *I : *N) { 16170946e70aSDimitry Andric MachineBasicBlock *SB = I->getBlock(); 161806c3fb27SDimitry Andric Block SBA = findBlock(SB); 16190946e70aSDimitry Andric linkBlockRefs(DefM, SBA); 16200946e70aSDimitry Andric } 16210946e70aSDimitry Andric 16220946e70aSDimitry Andric // Link the phi uses from the successor blocks. 162306c3fb27SDimitry Andric auto IsUseForBA = [BA](Node NA) -> bool { 16240946e70aSDimitry Andric if (NA.Addr->getKind() != NodeAttrs::Use) 16250946e70aSDimitry Andric return false; 16260946e70aSDimitry Andric assert(NA.Addr->getFlags() & NodeAttrs::PhiRef); 162706c3fb27SDimitry Andric return PhiUse(NA).Addr->getPredecessor() == BA.Id; 16280946e70aSDimitry Andric }; 16290946e70aSDimitry Andric 163006c3fb27SDimitry Andric RegisterAggr EHLiveIns = getLandingPadLiveIns(); 16310946e70aSDimitry Andric MachineBasicBlock *MBB = BA.Addr->getCode(); 16320946e70aSDimitry Andric 16330946e70aSDimitry Andric for (MachineBasicBlock *SB : MBB->successors()) { 16340946e70aSDimitry Andric bool IsEHPad = SB->isEHPad(); 163506c3fb27SDimitry Andric Block SBA = findBlock(SB); 163606c3fb27SDimitry Andric for (Instr IA : SBA.Addr->members_if(IsPhi, *this)) { 16370946e70aSDimitry Andric // Do not link phi uses for landing pad live-ins. 16380946e70aSDimitry Andric if (IsEHPad) { 16390946e70aSDimitry Andric // Find what register this phi is for. 164006c3fb27SDimitry Andric Ref RA = IA.Addr->getFirstMember(*this); 16410946e70aSDimitry Andric assert(RA.Id != 0); 164206c3fb27SDimitry Andric if (EHLiveIns.hasCoverOf(RA.Addr->getRegRef(*this))) 16430946e70aSDimitry Andric continue; 16440946e70aSDimitry Andric } 16450946e70aSDimitry Andric // Go over each phi use associated with MBB, and link it. 16460946e70aSDimitry Andric for (auto U : IA.Addr->members_if(IsUseForBA, *this)) { 164706c3fb27SDimitry Andric PhiUse PUA = U; 16480946e70aSDimitry Andric RegisterRef RR = PUA.Addr->getRegRef(*this); 16490946e70aSDimitry Andric linkRefUp<UseNode *>(IA, PUA, DefM[RR.Reg]); 16500946e70aSDimitry Andric } 16510946e70aSDimitry Andric } 16520946e70aSDimitry Andric } 16530946e70aSDimitry Andric 16540946e70aSDimitry Andric // Pop all defs from this block from the definition stacks. 16550946e70aSDimitry Andric releaseBlock(BA.Id, DefM); 16560946e70aSDimitry Andric } 16570946e70aSDimitry Andric 16580946e70aSDimitry Andric // Remove the use node UA from any data-flow and structural links. 165906c3fb27SDimitry Andric void DataFlowGraph::unlinkUseDF(Use UA) { 16600946e70aSDimitry Andric NodeId RD = UA.Addr->getReachingDef(); 16610946e70aSDimitry Andric NodeId Sib = UA.Addr->getSibling(); 16620946e70aSDimitry Andric 16630946e70aSDimitry Andric if (RD == 0) { 16640946e70aSDimitry Andric assert(Sib == 0); 16650946e70aSDimitry Andric return; 16660946e70aSDimitry Andric } 16670946e70aSDimitry Andric 16680946e70aSDimitry Andric auto RDA = addr<DefNode *>(RD); 16690946e70aSDimitry Andric auto TA = addr<UseNode *>(RDA.Addr->getReachedUse()); 16700946e70aSDimitry Andric if (TA.Id == UA.Id) { 16710946e70aSDimitry Andric RDA.Addr->setReachedUse(Sib); 16720946e70aSDimitry Andric return; 16730946e70aSDimitry Andric } 16740946e70aSDimitry Andric 16750946e70aSDimitry Andric while (TA.Id != 0) { 16760946e70aSDimitry Andric NodeId S = TA.Addr->getSibling(); 16770946e70aSDimitry Andric if (S == UA.Id) { 16780946e70aSDimitry Andric TA.Addr->setSibling(UA.Addr->getSibling()); 16790946e70aSDimitry Andric return; 16800946e70aSDimitry Andric } 16810946e70aSDimitry Andric TA = addr<UseNode *>(S); 16820946e70aSDimitry Andric } 16830946e70aSDimitry Andric } 16840946e70aSDimitry Andric 16850946e70aSDimitry Andric // Remove the def node DA from any data-flow and structural links. 168606c3fb27SDimitry Andric void DataFlowGraph::unlinkDefDF(Def DA) { 16870946e70aSDimitry Andric // 16880946e70aSDimitry Andric // RD 16890946e70aSDimitry Andric // | reached 16900946e70aSDimitry Andric // | def 16910946e70aSDimitry Andric // : 16920946e70aSDimitry Andric // . 16930946e70aSDimitry Andric // +----+ 16940946e70aSDimitry Andric // ... -- | DA | -- ... -- 0 : sibling chain of DA 16950946e70aSDimitry Andric // +----+ 16960946e70aSDimitry Andric // | | reached 16970946e70aSDimitry Andric // | : def 16980946e70aSDimitry Andric // | . 16990946e70aSDimitry Andric // | ... : Siblings (defs) 17000946e70aSDimitry Andric // | 17010946e70aSDimitry Andric // : reached 17020946e70aSDimitry Andric // . use 17030946e70aSDimitry Andric // ... : sibling chain of reached uses 17040946e70aSDimitry Andric 17050946e70aSDimitry Andric NodeId RD = DA.Addr->getReachingDef(); 17060946e70aSDimitry Andric 17070946e70aSDimitry Andric // Visit all siblings of the reached def and reset their reaching defs. 17080946e70aSDimitry Andric // Also, defs reached by DA are now "promoted" to being reached by RD, 17090946e70aSDimitry Andric // so all of them will need to be spliced into the sibling chain where 17100946e70aSDimitry Andric // DA belongs. 17110946e70aSDimitry Andric auto getAllNodes = [this](NodeId N) -> NodeList { 17120946e70aSDimitry Andric NodeList Res; 17130946e70aSDimitry Andric while (N) { 17140946e70aSDimitry Andric auto RA = addr<RefNode *>(N); 17150946e70aSDimitry Andric // Keep the nodes in the exact sibling order. 17160946e70aSDimitry Andric Res.push_back(RA); 17170946e70aSDimitry Andric N = RA.Addr->getSibling(); 17180946e70aSDimitry Andric } 17190946e70aSDimitry Andric return Res; 17200946e70aSDimitry Andric }; 17210946e70aSDimitry Andric NodeList ReachedDefs = getAllNodes(DA.Addr->getReachedDef()); 17220946e70aSDimitry Andric NodeList ReachedUses = getAllNodes(DA.Addr->getReachedUse()); 17230946e70aSDimitry Andric 17240946e70aSDimitry Andric if (RD == 0) { 172506c3fb27SDimitry Andric for (Ref I : ReachedDefs) 17260946e70aSDimitry Andric I.Addr->setSibling(0); 172706c3fb27SDimitry Andric for (Ref I : ReachedUses) 17280946e70aSDimitry Andric I.Addr->setSibling(0); 17290946e70aSDimitry Andric } 173006c3fb27SDimitry Andric for (Def I : ReachedDefs) 17310946e70aSDimitry Andric I.Addr->setReachingDef(RD); 173206c3fb27SDimitry Andric for (Use I : ReachedUses) 17330946e70aSDimitry Andric I.Addr->setReachingDef(RD); 17340946e70aSDimitry Andric 17350946e70aSDimitry Andric NodeId Sib = DA.Addr->getSibling(); 17360946e70aSDimitry Andric if (RD == 0) { 17370946e70aSDimitry Andric assert(Sib == 0); 17380946e70aSDimitry Andric return; 17390946e70aSDimitry Andric } 17400946e70aSDimitry Andric 17410946e70aSDimitry Andric // Update the reaching def node and remove DA from the sibling list. 17420946e70aSDimitry Andric auto RDA = addr<DefNode *>(RD); 17430946e70aSDimitry Andric auto TA = addr<DefNode *>(RDA.Addr->getReachedDef()); 17440946e70aSDimitry Andric if (TA.Id == DA.Id) { 17450946e70aSDimitry Andric // If DA is the first reached def, just update the RD's reached def 17460946e70aSDimitry Andric // to the DA's sibling. 17470946e70aSDimitry Andric RDA.Addr->setReachedDef(Sib); 17480946e70aSDimitry Andric } else { 17490946e70aSDimitry Andric // Otherwise, traverse the sibling list of the reached defs and remove 17500946e70aSDimitry Andric // DA from it. 17510946e70aSDimitry Andric while (TA.Id != 0) { 17520946e70aSDimitry Andric NodeId S = TA.Addr->getSibling(); 17530946e70aSDimitry Andric if (S == DA.Id) { 17540946e70aSDimitry Andric TA.Addr->setSibling(Sib); 17550946e70aSDimitry Andric break; 17560946e70aSDimitry Andric } 17570946e70aSDimitry Andric TA = addr<DefNode *>(S); 17580946e70aSDimitry Andric } 17590946e70aSDimitry Andric } 17600946e70aSDimitry Andric 17610946e70aSDimitry Andric // Splice the DA's reached defs into the RDA's reached def chain. 17620946e70aSDimitry Andric if (!ReachedDefs.empty()) { 176306c3fb27SDimitry Andric auto Last = Def(ReachedDefs.back()); 17640946e70aSDimitry Andric Last.Addr->setSibling(RDA.Addr->getReachedDef()); 17650946e70aSDimitry Andric RDA.Addr->setReachedDef(ReachedDefs.front().Id); 17660946e70aSDimitry Andric } 17670946e70aSDimitry Andric // Splice the DA's reached uses into the RDA's reached use chain. 17680946e70aSDimitry Andric if (!ReachedUses.empty()) { 176906c3fb27SDimitry Andric auto Last = Use(ReachedUses.back()); 17700946e70aSDimitry Andric Last.Addr->setSibling(RDA.Addr->getReachedUse()); 17710946e70aSDimitry Andric RDA.Addr->setReachedUse(ReachedUses.front().Id); 17720946e70aSDimitry Andric } 17730946e70aSDimitry Andric } 177406c3fb27SDimitry Andric 177506c3fb27SDimitry Andric bool DataFlowGraph::isTracked(RegisterRef RR) const { 177606c3fb27SDimitry Andric return !disjoint(getPRI().getUnits(RR), TrackedUnits); 177706c3fb27SDimitry Andric } 177806c3fb27SDimitry Andric 177906c3fb27SDimitry Andric bool DataFlowGraph::hasUntrackedRef(Stmt S, bool IgnoreReserved) const { 178006c3fb27SDimitry Andric SmallVector<MachineOperand *> Ops; 178106c3fb27SDimitry Andric 178206c3fb27SDimitry Andric for (Ref R : S.Addr->members(*this)) { 178306c3fb27SDimitry Andric Ops.push_back(&R.Addr->getOp()); 178406c3fb27SDimitry Andric RegisterRef RR = R.Addr->getRegRef(*this); 178506c3fb27SDimitry Andric if (IgnoreReserved && RR.isReg() && ReservedRegs[RR.idx()]) 178606c3fb27SDimitry Andric continue; 178706c3fb27SDimitry Andric if (!isTracked(RR)) 178806c3fb27SDimitry Andric return true; 178906c3fb27SDimitry Andric } 179006c3fb27SDimitry Andric for (const MachineOperand &Op : S.Addr->getCode()->operands()) { 179106c3fb27SDimitry Andric if (!Op.isReg() && !Op.isRegMask()) 179206c3fb27SDimitry Andric continue; 17937a6dacacSDimitry Andric if (!llvm::is_contained(Ops, &Op)) 179406c3fb27SDimitry Andric return true; 179506c3fb27SDimitry Andric } 179606c3fb27SDimitry Andric return false; 179706c3fb27SDimitry Andric } 179806c3fb27SDimitry Andric 179906c3fb27SDimitry Andric } // end namespace llvm::rdf 1800