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"
21fe013be4SDimitry 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.
43fe013be4SDimitry Andric namespace llvm::rdf {
440946e70aSDimitry Andric
operator <<(raw_ostream & OS,const Print<RegisterRef> & P)450946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterRef> &P) {
46fe013be4SDimitry Andric P.G.getPRI().print(OS, P.Obj);
470946e70aSDimitry Andric return OS;
480946e70aSDimitry Andric }
490946e70aSDimitry Andric
operator <<(raw_ostream & OS,const Print<NodeId> & P)500946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<NodeId> &P) {
51fe013be4SDimitry Andric if (P.Obj == 0)
52fe013be4SDimitry 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) {
60fe013be4SDimitry Andric case NodeAttrs::Func:
61fe013be4SDimitry Andric OS << 'f';
62fe013be4SDimitry Andric break;
63fe013be4SDimitry Andric case NodeAttrs::Block:
64fe013be4SDimitry Andric OS << 'b';
65fe013be4SDimitry Andric break;
66fe013be4SDimitry Andric case NodeAttrs::Stmt:
67fe013be4SDimitry Andric OS << 's';
68fe013be4SDimitry Andric break;
69fe013be4SDimitry Andric case NodeAttrs::Phi:
70fe013be4SDimitry Andric OS << 'p';
71fe013be4SDimitry Andric break;
72fe013be4SDimitry Andric default:
73fe013be4SDimitry Andric OS << "c?";
74fe013be4SDimitry 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) {
87fe013be4SDimitry Andric case NodeAttrs::Use:
88fe013be4SDimitry Andric OS << 'u';
89fe013be4SDimitry Andric break;
90fe013be4SDimitry Andric case NodeAttrs::Def:
91fe013be4SDimitry Andric OS << 'd';
92fe013be4SDimitry Andric break;
93fe013be4SDimitry Andric case NodeAttrs::Block:
94fe013be4SDimitry Andric OS << 'b';
95fe013be4SDimitry Andric break;
96fe013be4SDimitry Andric default:
97fe013be4SDimitry Andric OS << "r?";
98fe013be4SDimitry 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
printRefHeader(raw_ostream & OS,const Ref RA,const DataFlowGraph & G)111fe013be4SDimitry Andric static void printRefHeader(raw_ostream &OS, const Ref RA,
1120946e70aSDimitry Andric const DataFlowGraph &G) {
113fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Def> & P)118fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Use> & P)135fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<PhiUse> & P)146fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Ref> & P)160fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<NodeList> & P)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
operator <<(raw_ostream & OS,const Print<NodeSet> & P)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
197fe013be4SDimitry Andric template <typename T> struct PrintListV {
PrintListVllvm::rdf::__anon5a868eb80111::PrintListV1980946e70aSDimitry 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>
operator <<(raw_ostream & OS,const PrintListV<T> & P)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
operator <<(raw_ostream & OS,const Print<Phi> & P)218fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Stmt> & P)224fe013be4SDimitry 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 =
231fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Instr> & P)248fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<Block> & P)263fe013be4SDimitry 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;
2670946e70aSDimitry Andric auto PrintBBs = [&OS](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
operator <<(raw_ostream & OS,const Print<Func> & P)295fe013be4SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<Func> &P) {
296fe013be4SDimitry Andric OS << "DFG dump:[\n"
297fe013be4SDimitry Andric << Print(P.Obj.Id, P.G)
298fe013be4SDimitry 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
operator <<(raw_ostream & OS,const Print<RegisterSet> & P)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
operator <<(raw_ostream & OS,const Print<RegisterAggr> & P)3130946e70aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterAggr> &P) {
314fe013be4SDimitry Andric OS << P.Obj;
3150946e70aSDimitry Andric return OS;
3160946e70aSDimitry Andric }
3170946e70aSDimitry Andric
operator <<(raw_ostream & OS,const Print<DataFlowGraph::DefStack> & P)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;) {
321fe013be4SDimitry Andric OS << Print(I->Id, P.G) << '<' << Print(I->Addr->getRegRef(P.G), P.G)
322fe013be4SDimitry 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 //
startNewBlock()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
needNewBlock()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
New()360fe013be4SDimitry 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;
366fe013be4SDimitry Andric Node NA = {reinterpret_cast<NodeBase *>(ActiveEnd), makeId(ActiveB, Index)};
3670946e70aSDimitry Andric ActiveEnd += NodeMemSize;
3680946e70aSDimitry Andric return NA;
3690946e70aSDimitry Andric }
3700946e70aSDimitry Andric
id(const NodeBase * P) const3710946e70aSDimitry 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
clear()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.
append(Node NA)390fe013be4SDimitry 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.
getRegRef(const DataFlowGraph & G) const4020946e70aSDimitry Andric RegisterRef RefNode::getRegRef(const DataFlowGraph &G) const {
4030946e70aSDimitry Andric assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
4040946e70aSDimitry Andric if (NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef)
405fe013be4SDimitry Andric return G.unpack(RefData.PR);
406fe013be4SDimitry Andric assert(RefData.Op != nullptr);
407fe013be4SDimitry 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).
setRegRef(RegisterRef RR,DataFlowGraph & G)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);
415fe013be4SDimitry 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).
setRegRef(MachineOperand * Op,DataFlowGraph & G)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;
424fe013be4SDimitry Andric RefData.Op = Op;
4250946e70aSDimitry Andric }
4260946e70aSDimitry Andric
4270946e70aSDimitry Andric // Get the owner of a given reference node.
getOwner(const DataFlowGraph & G)428fe013be4SDimitry Andric Node RefNode::getOwner(const DataFlowGraph &G) {
429fe013be4SDimitry 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.
linkToDef(NodeId Self,Def DA)440fe013be4SDimitry Andric void DefNode::linkToDef(NodeId Self, Def DA) {
441fe013be4SDimitry Andric RefData.RD = DA.Id;
442fe013be4SDimitry 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.
linkToDef(NodeId Self,Def DA)447fe013be4SDimitry Andric void UseNode::linkToDef(NodeId Self, Def DA) {
448fe013be4SDimitry Andric RefData.RD = DA.Id;
449fe013be4SDimitry 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.
getFirstMember(const DataFlowGraph & G) const454fe013be4SDimitry Andric Node CodeNode::getFirstMember(const DataFlowGraph &G) const {
455fe013be4SDimitry Andric if (CodeData.FirstM == 0)
456fe013be4SDimitry Andric return Node();
457fe013be4SDimitry Andric return G.addr<NodeBase *>(CodeData.FirstM);
4580946e70aSDimitry Andric }
4590946e70aSDimitry Andric
4600946e70aSDimitry Andric // Get the last member of the code node.
getLastMember(const DataFlowGraph & G) const461fe013be4SDimitry Andric Node CodeNode::getLastMember(const DataFlowGraph &G) const {
462fe013be4SDimitry Andric if (CodeData.LastM == 0)
463fe013be4SDimitry Andric return Node();
464fe013be4SDimitry 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.
addMember(Node NA,const DataFlowGraph & G)468fe013be4SDimitry Andric void CodeNode::addMember(Node NA, const DataFlowGraph &G) {
469fe013be4SDimitry Andric Node ML = getLastMember(G);
4700946e70aSDimitry Andric if (ML.Id != 0) {
4710946e70aSDimitry Andric ML.Addr->append(NA);
4720946e70aSDimitry Andric } else {
473fe013be4SDimitry Andric CodeData.FirstM = NA.Id;
4740946e70aSDimitry Andric NodeId Self = G.id(this);
4750946e70aSDimitry Andric NA.Addr->setNext(Self);
4760946e70aSDimitry Andric }
477fe013be4SDimitry Andric CodeData.LastM = NA.Id;
4780946e70aSDimitry Andric }
4790946e70aSDimitry Andric
4800946e70aSDimitry Andric // Add node NA after member node MA in the given code node.
addMemberAfter(Node MA,Node NA,const DataFlowGraph & G)481fe013be4SDimitry Andric void CodeNode::addMemberAfter(Node MA, Node NA, const DataFlowGraph &G) {
4820946e70aSDimitry Andric MA.Addr->append(NA);
483fe013be4SDimitry Andric if (CodeData.LastM == MA.Id)
484fe013be4SDimitry Andric CodeData.LastM = NA.Id;
4850946e70aSDimitry Andric }
4860946e70aSDimitry Andric
4870946e70aSDimitry Andric // Remove member node NA from the given code node.
removeMember(Node NA,const DataFlowGraph & G)488fe013be4SDimitry Andric void CodeNode::removeMember(Node NA, const DataFlowGraph &G) {
489fe013be4SDimitry 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) {
494fe013be4SDimitry Andric if (CodeData.LastM == MA.Id) {
4950946e70aSDimitry Andric // If it is the only member, set both first and last to 0.
496fe013be4SDimitry Andric CodeData.FirstM = CodeData.LastM = 0;
4970946e70aSDimitry Andric } else {
4980946e70aSDimitry Andric // Otherwise, advance the first member.
499fe013be4SDimitry 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.
510fe013be4SDimitry Andric if (CodeData.LastM == NA.Id)
511fe013be4SDimitry 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.
members(const DataFlowGraph & G) const5200946e70aSDimitry Andric NodeList CodeNode::members(const DataFlowGraph &G) const {
521fe013be4SDimitry 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.
getOwner(const DataFlowGraph & G)526fe013be4SDimitry Andric Node InstrNode::getOwner(const DataFlowGraph &G) {
527fe013be4SDimitry 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.
addPhi(Phi PA,const DataFlowGraph & G)539fe013be4SDimitry Andric void BlockNode::addPhi(Phi PA, const DataFlowGraph &G) {
540fe013be4SDimitry 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.
550fe013be4SDimitry 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);
555fe013be4SDimitry 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.
findBlock(const MachineBasicBlock * BB,const DataFlowGraph & G) const569fe013be4SDimitry Andric Block FuncNode::findBlock(const MachineBasicBlock *BB,
5700946e70aSDimitry Andric const DataFlowGraph &G) const {
571fe013be4SDimitry 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];
575fe013be4SDimitry Andric return Block();
5760946e70aSDimitry Andric }
5770946e70aSDimitry Andric
5780946e70aSDimitry Andric // Get the block node for the entry block in the given function.
getEntryBlock(const DataFlowGraph & G)579fe013be4SDimitry 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.
isPreserving(const MachineInstr & In,unsigned OpNum) const589fe013be4SDimitry Andric bool TargetOperandInfo::isPreserving(const MachineInstr &In,
590fe013be4SDimitry 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.
isClobbering(const MachineInstr & In,unsigned OpNum) const595fe013be4SDimitry Andric bool TargetOperandInfo::isClobbering(const MachineInstr &In,
596fe013be4SDimitry 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
isFixedReg(const MachineInstr & In,unsigned OpNum) const608fe013be4SDimitry Andric bool TargetOperandInfo::isFixedReg(const MachineInstr &In,
609fe013be4SDimitry 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
DataFlowGraph(MachineFunction & mf,const TargetInstrInfo & tii,const TargetRegisterInfo & tri,const MachineDominatorTree & mdt,const MachineDominanceFrontier & mdf)6370946e70aSDimitry Andric DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii,
638fe013be4SDimitry Andric const TargetRegisterInfo &tri,
639fe013be4SDimitry 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),
643fe013be4SDimitry Andric LiveIns(PRI) {}
644bdd1243dSDimitry Andric
DataFlowGraph(MachineFunction & mf,const TargetInstrInfo & tii,const TargetRegisterInfo & tri,const MachineDominatorTree & mdt,const MachineDominanceFrontier & mdf,const TargetOperandInfo & toi)645bdd1243dSDimitry Andric DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii,
646fe013be4SDimitry Andric const TargetRegisterInfo &tri,
647fe013be4SDimitry Andric const MachineDominatorTree &mdt,
648fe013be4SDimitry Andric const MachineDominanceFrontier &mdf,
649fe013be4SDimitry Andric const TargetOperandInfo &toi)
6500946e70aSDimitry Andric : MF(mf), TII(tii), TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(toi),
651fe013be4SDimitry 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.
Iterator(const DataFlowGraph::DefStack & S,bool Top)6590946e70aSDimitry Andric DataFlowGraph::DefStack::Iterator::Iterator(const DataFlowGraph::DefStack &S,
660fe013be4SDimitry Andric bool Top)
661fe013be4SDimitry 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.
size() const6740946e70aSDimitry 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.
pop()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.
start_block(NodeId N)6910946e70aSDimitry Andric void DataFlowGraph::DefStack::start_block(NodeId N) {
6920946e70aSDimitry Andric assert(N != 0);
693fe013be4SDimitry 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.
clear_block(NodeId 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.
nextUp(unsigned P) const7130946e70aSDimitry 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.
nextDown(unsigned P) const7280946e70aSDimitry 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
getLandingPadLiveIns() const744fe013be4SDimitry Andric RegisterAggr DataFlowGraph::getLandingPadLiveIns() const {
745fe013be4SDimitry Andric RegisterAggr LR(getPRI());
7460946e70aSDimitry Andric const Function &F = MF.getFunction();
747fe013be4SDimitry 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.
ptr(NodeId N) const7610946e70aSDimitry 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.
id(const NodeBase * P) const7680946e70aSDimitry 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.
newNode(uint16_t Attrs)775fe013be4SDimitry Andric Node DataFlowGraph::newNode(uint16_t Attrs) {
776fe013be4SDimitry 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.
cloneNode(const Node B)784fe013be4SDimitry Andric Node DataFlowGraph::cloneNode(const Node B) {
785fe013be4SDimitry 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) {
789fe013be4SDimitry Andric Ref RA = NA;
7900946e70aSDimitry Andric RA.Addr->setReachingDef(0);
7910946e70aSDimitry Andric RA.Addr->setSibling(0);
7920946e70aSDimitry Andric if (NA.Addr->getKind() == NodeAttrs::Def) {
793fe013be4SDimitry 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
newUse(Instr Owner,MachineOperand & Op,uint16_t Flags)803fe013be4SDimitry Andric Use DataFlowGraph::newUse(Instr Owner, MachineOperand &Op, uint16_t Flags) {
804fe013be4SDimitry Andric Use UA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags);
8050946e70aSDimitry Andric UA.Addr->setRegRef(&Op, *this);
8060946e70aSDimitry Andric return UA;
8070946e70aSDimitry Andric }
8080946e70aSDimitry Andric
newPhiUse(Phi Owner,RegisterRef RR,Block PredB,uint16_t Flags)809fe013be4SDimitry Andric PhiUse DataFlowGraph::newPhiUse(Phi Owner, RegisterRef RR, Block PredB,
810fe013be4SDimitry Andric uint16_t Flags) {
811fe013be4SDimitry 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
newDef(Instr Owner,MachineOperand & Op,uint16_t Flags)818fe013be4SDimitry Andric Def DataFlowGraph::newDef(Instr Owner, MachineOperand &Op, uint16_t Flags) {
819fe013be4SDimitry Andric Def DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags);
8200946e70aSDimitry Andric DA.Addr->setRegRef(&Op, *this);
8210946e70aSDimitry Andric return DA;
8220946e70aSDimitry Andric }
8230946e70aSDimitry Andric
newDef(Instr Owner,RegisterRef RR,uint16_t Flags)824fe013be4SDimitry Andric Def DataFlowGraph::newDef(Instr Owner, RegisterRef RR, uint16_t Flags) {
825fe013be4SDimitry 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
newPhi(Block Owner)831fe013be4SDimitry Andric Phi DataFlowGraph::newPhi(Block Owner) {
832fe013be4SDimitry Andric Phi PA = newNode(NodeAttrs::Code | NodeAttrs::Phi);
8330946e70aSDimitry Andric Owner.Addr->addPhi(PA, *this);
8340946e70aSDimitry Andric return PA;
8350946e70aSDimitry Andric }
8360946e70aSDimitry Andric
newStmt(Block Owner,MachineInstr * MI)837fe013be4SDimitry Andric Stmt DataFlowGraph::newStmt(Block Owner, MachineInstr *MI) {
838fe013be4SDimitry 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
newBlock(Func Owner,MachineBasicBlock * BB)844fe013be4SDimitry Andric Block DataFlowGraph::newBlock(Func Owner, MachineBasicBlock *BB) {
845fe013be4SDimitry 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
newFunc(MachineFunction * MF)851fe013be4SDimitry Andric Func DataFlowGraph::newFunc(MachineFunction *MF) {
852fe013be4SDimitry 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.
build(const Config & config)858fe013be4SDimitry Andric void DataFlowGraph::build(const Config &config) {
8590946e70aSDimitry Andric reset();
860fe013be4SDimitry Andric BuildCfg = config;
861fe013be4SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
862fe013be4SDimitry Andric ReservedRegs = MRI.getReservedRegs();
863fe013be4SDimitry Andric bool SkipReserved = BuildCfg.Options & BuildOptions::OmitReserved;
864fe013be4SDimitry Andric
865fe013be4SDimitry Andric auto Insert = [](auto &Set, auto &&Range) {
866fe013be4SDimitry Andric Set.insert(Range.begin(), Range.end());
867fe013be4SDimitry Andric };
868fe013be4SDimitry Andric
869fe013be4SDimitry Andric if (BuildCfg.TrackRegs.empty()) {
870fe013be4SDimitry Andric std::set<RegisterId> BaseSet;
871fe013be4SDimitry Andric if (BuildCfg.Classes.empty()) {
872fe013be4SDimitry Andric // Insert every register.
873fe013be4SDimitry Andric for (unsigned R = 0, E = getPRI().getTRI().getNumRegs(); R != E; ++R)
874fe013be4SDimitry Andric BaseSet.insert(R);
875fe013be4SDimitry Andric } else {
876fe013be4SDimitry Andric for (const TargetRegisterClass *RC : BuildCfg.Classes) {
877fe013be4SDimitry Andric for (MCPhysReg R : *RC)
878fe013be4SDimitry Andric BaseSet.insert(R);
879fe013be4SDimitry Andric }
880fe013be4SDimitry Andric }
881fe013be4SDimitry Andric for (RegisterId R : BaseSet) {
882fe013be4SDimitry Andric if (SkipReserved && ReservedRegs[R])
883fe013be4SDimitry Andric continue;
884fe013be4SDimitry Andric Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R)));
885fe013be4SDimitry Andric }
886fe013be4SDimitry Andric } else {
887fe013be4SDimitry Andric // Track set in Config overrides everything.
888fe013be4SDimitry Andric for (unsigned R : BuildCfg.TrackRegs) {
889fe013be4SDimitry Andric if (SkipReserved && ReservedRegs[R])
890fe013be4SDimitry Andric continue;
891fe013be4SDimitry Andric Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R)));
892fe013be4SDimitry Andric }
893fe013be4SDimitry Andric }
894fe013be4SDimitry Andric
895fe013be4SDimitry Andric TheFunc = newFunc(&MF);
8960946e70aSDimitry Andric
8970946e70aSDimitry Andric if (MF.empty())
8980946e70aSDimitry Andric return;
8990946e70aSDimitry Andric
9000946e70aSDimitry Andric for (MachineBasicBlock &B : MF) {
901fe013be4SDimitry 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
910fe013be4SDimitry Andric Block EA = TheFunc.Addr->getEntryBlock(*this);
911fe013be4SDimitry 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.
924fe013be4SDimitry Andric for (RegisterRef RR : LiveIns.refs()) {
925fe013be4SDimitry Andric if (RR.isReg() && !isTracked(RR)) // isReg is likely guaranteed
926fe013be4SDimitry Andric continue;
927fe013be4SDimitry Andric Phi PA = newPhi(EA);
9280946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
929fe013be4SDimitry 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.
938fe013be4SDimitry Andric RegisterAggr EHRegs = getLandingPadLiveIns();
9390946e70aSDimitry Andric if (!EHRegs.empty()) {
940fe013be4SDimitry 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.
951fe013be4SDimitry Andric for (RegisterRef RR : EHRegs.refs()) {
952fe013be4SDimitry Andric if (RR.isReg() && !isTracked(RR))
953fe013be4SDimitry Andric continue;
954fe013be4SDimitry Andric Phi PA = newPhi(BA);
9550946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
9560946e70aSDimitry Andric // Add def:
957fe013be4SDimitry Andric Def DA = newDef(PA, RR, PhiFlags);
9580946e70aSDimitry Andric PA.Addr->addMember(DA, *this);
9590946e70aSDimitry Andric // Add uses (no reaching defs for phi uses):
960fe013be4SDimitry Andric for (Block PBA : Preds) {
961fe013be4SDimitry 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.
970fe013be4SDimitry Andric BlockRefsMap PhiM(getPRI());
971fe013be4SDimitry Andric for (Block BA : Blocks)
9720946e70aSDimitry Andric recordDefsForDF(PhiM, BA);
973fe013be4SDimitry Andric for (Block BA : Blocks)
974fe013be4SDimitry 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.
981fe013be4SDimitry Andric if (!(BuildCfg.Options & BuildOptions::KeepDeadPhis))
9820946e70aSDimitry Andric removeUnusedPhis();
9830946e70aSDimitry Andric }
9840946e70aSDimitry Andric
makeRegRef(unsigned Reg,unsigned Sub) const9850946e70aSDimitry Andric RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const {
986fe013be4SDimitry 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
makeRegRef(const MachineOperand & Op) const9930946e70aSDimitry 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());
997fe013be4SDimitry Andric return RegisterRef(getPRI().getRegMaskId(Op.getRegMask()),
998fe013be4SDimitry Andric LaneBitmask::getAll());
9990946e70aSDimitry Andric }
10000946e70aSDimitry Andric
10010946e70aSDimitry Andric // For each stack in the map DefM, push the delimiter for block B on it.
markBlock(NodeId B,DefStackMap & DefM)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.
releaseBlock(NodeId B,DefStackMap & 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.
pushAllDefs(Instr IA,DefStackMap & DefM)1027fe013be4SDimitry 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.
pushClobbers(Instr IA,DefStackMap & DefM)1034fe013be4SDimitry 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
1050fe013be4SDimitry 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);
1057fe013be4SDimitry 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);
1064fe013be4SDimitry Andric for (RegisterId A : getPRI().getAliasSet(RR.Reg)) {
1065fe013be4SDimitry Andric if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A)))
1066fe013be4SDimitry 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.
1073fe013be4SDimitry 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.
pushDefs(Instr IA,DefStackMap & DefM)1080fe013be4SDimitry 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
1098fe013be4SDimitry 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);
1105fe013be4SDimitry 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) {
1111fe013be4SDimitry Andric MachineInstr *MI = Stmt(IA).Addr->getCode();
1112fe013be4SDimitry Andric dbgs() << "Multiple definitions of register: " << Print(RR, *this)
1113fe013be4SDimitry Andric << " in\n " << *MI << "in " << printMBBReference(*MI->getParent())
1114fe013be4SDimitry 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);
1121fe013be4SDimitry Andric for (RegisterId A : getPRI().getAliasSet(RR.Reg)) {
1122fe013be4SDimitry Andric if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A)))
1123fe013be4SDimitry 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.
1129fe013be4SDimitry 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".
getRelatedRefs(Instr IA,Ref RA) const1136fe013be4SDimitry 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.
reset()11490946e70aSDimitry Andric void DataFlowGraph::reset() {
11500946e70aSDimitry Andric Memory.clear();
11510946e70aSDimitry Andric BlockNodes.clear();
1152fe013be4SDimitry Andric TrackedUnits.clear();
1153fe013be4SDimitry Andric ReservedRegs.clear();
1154fe013be4SDimitry 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.
getNextRelated(Instr IA,Ref RA) const1163fe013be4SDimitry Andric Ref DataFlowGraph::getNextRelated(Instr IA, Ref RA) const {
11640946e70aSDimitry Andric assert(IA.Id != 0 && RA.Id != 0);
11650946e70aSDimitry Andric
1166fe013be4SDimitry Andric auto IsRelated = [this, RA](Ref TA) -> bool {
11670946e70aSDimitry Andric if (TA.Addr->getKind() != RA.Addr->getKind())
11680946e70aSDimitry Andric return false;
1169fe013be4SDimitry Andric if (!getPRI().equal_to(TA.Addr->getRegRef(*this),
1170fe013be4SDimitry Andric RA.Addr->getRegRef(*this))) {
11710946e70aSDimitry Andric return false;
1172fe013be4SDimitry Andric }
11730946e70aSDimitry Andric return true;
11740946e70aSDimitry Andric };
1175fe013be4SDimitry Andric
1176fe013be4SDimitry Andric RegisterRef RR = RA.Addr->getRegRef(*this);
1177fe013be4SDimitry Andric if (IA.Addr->getKind() == NodeAttrs::Stmt) {
1178fe013be4SDimitry Andric auto Cond = [&IsRelated, RA](Ref TA) -> bool {
1179fe013be4SDimitry Andric return IsRelated(TA) && &RA.Addr->getOp() == &TA.Addr->getOp();
11800946e70aSDimitry Andric };
1181fe013be4SDimitry Andric return RA.Addr->getNextRef(RR, Cond, true, *this);
1182fe013be4SDimitry Andric }
1183fe013be4SDimitry Andric
1184fe013be4SDimitry Andric assert(IA.Addr->getKind() == NodeAttrs::Phi);
1185fe013be4SDimitry Andric auto Cond = [&IsRelated, RA](Ref TA) -> bool {
1186fe013be4SDimitry 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.
1191fe013be4SDimitry Andric return PhiUse(TA).Addr->getPredecessor() ==
1192fe013be4SDimitry Andric PhiUse(RA).Addr->getPredecessor();
11930946e70aSDimitry Andric };
1194fe013be4SDimitry 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>
locateNextRef(Instr IA,Ref RA,Predicate P) const1203fe013be4SDimitry 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
1207fe013be4SDimitry 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);
1220fe013be4SDimitry 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.
getNextShadow(Instr IA,Ref RA,bool Create)1225fe013be4SDimitry 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;
1229fe013be4SDimitry 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.
1237fe013be4SDimitry 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.
buildStmt(Block BA,MachineInstr & In)1245fe013be4SDimitry Andric void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) {
1246fe013be4SDimitry 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.
1268fe013be4SDimitry Andric for (const MachineOperand &Op : In.all_uses()) {
1269fe013be4SDimitry Andric if (Op.getReg() == 0 || Op.isUndef())
12700946e70aSDimitry Andric continue;
12710946e70aSDimitry Andric RegisterRef UR = makeRegRef(Op);
1272fe013be4SDimitry 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();
1292fe013be4SDimitry 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;
1307fe013be4SDimitry 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;
1319fe013be4SDimitry Andric uint16_t Flags = NodeAttrs::Clobbering | NodeAttrs::Fixed | NodeAttrs::Dead;
1320fe013be4SDimitry 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();
1324fe013be4SDimitry Andric for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) {
1325fe013be4SDimitry Andric if (!isTracked(RegisterRef(i)))
1326fe013be4SDimitry Andric continue;
13270946e70aSDimitry Andric if (!(RM[i / 32] & (1u << (i % 32))))
13280946e70aSDimitry Andric DoneClobbers.set(i);
13290946e70aSDimitry Andric }
1330fe013be4SDimitry 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();
1339fe013be4SDimitry 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 }
1358fe013be4SDimitry 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();
1368fe013be4SDimitry 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;
1375fe013be4SDimitry 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.
recordDefsForDF(BlockRefsMap & PhiM,Block BA)1382fe013be4SDimitry 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.
1397fe013be4SDimitry Andric RegisterAggr Defs(getPRI());
1398fe013be4SDimitry Andric for (Instr IA : BA.Addr->members(*this)) {
1399fe013be4SDimitry Andric for (Ref RA : IA.Addr->members_if(IsDef, *this)) {
1400fe013be4SDimitry Andric RegisterRef RR = RA.Addr->getRegRef(*this);
1401fe013be4SDimitry Andric if (RR.isReg() && isTracked(RR))
1402fe013be4SDimitry Andric Defs.insert(RR);
1403fe013be4SDimitry Andric }
1404fe013be4SDimitry 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) {
1418fe013be4SDimitry Andric Block DBA = findBlock(DB);
1419fe013be4SDimitry 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.
buildPhis(BlockRefsMap & PhiM,Block BA)1425fe013be4SDimitry 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
1438fe013be4SDimitry Andric const RegisterAggr &Defs = PhiM[BA.Id];
14390946e70aSDimitry Andric uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
14400946e70aSDimitry Andric
1441fe013be4SDimitry Andric for (RegisterRef RR : Defs.refs()) {
1442fe013be4SDimitry Andric Phi PA = newPhi(BA);
1443fe013be4SDimitry Andric PA.Addr->addMember(newDef(PA, RR, PhiFlags), *this);
1444fe013be4SDimitry Andric
1445fe013be4SDimitry Andric // Add phi uses.
1446fe013be4SDimitry Andric for (Block PBA : Preds) {
1447fe013be4SDimitry Andric PA.Addr->addMember(newPhiUse(PA, RR, PBA), *this);
1448fe013be4SDimitry Andric }
14490946e70aSDimitry Andric }
14500946e70aSDimitry Andric }
14510946e70aSDimitry Andric
14520946e70aSDimitry Andric // Remove any unneeded phi nodes that were created during the build process.
removeUnusedPhis()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;
1461fe013be4SDimitry 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 {
1467fe013be4SDimitry Andric for (Node M : Ms) {
14680946e70aSDimitry Andric if (M.Addr->getKind() != NodeAttrs::Def)
14690946e70aSDimitry Andric continue;
1470fe013be4SDimitry 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;
1486fe013be4SDimitry Andric for (Ref RA : Refs) {
14870946e70aSDimitry Andric if (NodeId RD = RA.Addr->getReachingDef()) {
14880946e70aSDimitry Andric auto RDA = addr<DefNode *>(RD);
1489fe013be4SDimitry 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 }
1498fe013be4SDimitry 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>
linkRefUp(Instr IA,NodeAddr<T> TA,DefStack & DS)1507fe013be4SDimitry 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.
1514fe013be4SDimitry 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.
1530fe013be4SDimitry 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>
linkStmtRefs(DefStackMap & DefM,Stmt SA,Predicate P)1551fe013be4SDimitry Andric void DataFlowGraph::linkStmtRefs(DefStackMap &DefM, Stmt SA, Predicate P) {
15520946e70aSDimitry Andric #ifndef NDEBUG
1553fe013be4SDimitry Andric RegisterSet Defs(getPRI());
15540946e70aSDimitry Andric #endif
15550946e70aSDimitry Andric
15560946e70aSDimitry Andric // Link all nodes (upwards in the data-flow) with their reaching defs.
1557fe013be4SDimitry 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.
linkBlockRefs(DefStackMap & DefM,Block BA)1582fe013be4SDimitry Andric void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, Block BA) {
15830946e70aSDimitry Andric // Push block delimiters.
15840946e70aSDimitry Andric markBlock(BA.Id, DefM);
15850946e70aSDimitry Andric
1586fe013be4SDimitry Andric auto IsClobber = [](Ref RA) -> bool {
15870946e70aSDimitry Andric return IsDef(RA) && (RA.Addr->getFlags() & NodeAttrs::Clobbering);
15880946e70aSDimitry Andric };
1589fe013be4SDimitry 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.
1597fe013be4SDimitry 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();
1618fe013be4SDimitry Andric Block SBA = findBlock(SB);
16190946e70aSDimitry Andric linkBlockRefs(DefM, SBA);
16200946e70aSDimitry Andric }
16210946e70aSDimitry Andric
16220946e70aSDimitry Andric // Link the phi uses from the successor blocks.
1623fe013be4SDimitry 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);
1627fe013be4SDimitry Andric return PhiUse(NA).Addr->getPredecessor() == BA.Id;
16280946e70aSDimitry Andric };
16290946e70aSDimitry Andric
1630fe013be4SDimitry 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();
1635fe013be4SDimitry Andric Block SBA = findBlock(SB);
1636fe013be4SDimitry 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.
1640fe013be4SDimitry Andric Ref RA = IA.Addr->getFirstMember(*this);
16410946e70aSDimitry Andric assert(RA.Id != 0);
1642fe013be4SDimitry 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)) {
1647fe013be4SDimitry 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.
unlinkUseDF(Use UA)1659fe013be4SDimitry 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.
unlinkDefDF(Def DA)1686fe013be4SDimitry 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) {
1725fe013be4SDimitry Andric for (Ref I : ReachedDefs)
17260946e70aSDimitry Andric I.Addr->setSibling(0);
1727fe013be4SDimitry Andric for (Ref I : ReachedUses)
17280946e70aSDimitry Andric I.Addr->setSibling(0);
17290946e70aSDimitry Andric }
1730fe013be4SDimitry Andric for (Def I : ReachedDefs)
17310946e70aSDimitry Andric I.Addr->setReachingDef(RD);
1732fe013be4SDimitry 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()) {
1763fe013be4SDimitry 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()) {
1769fe013be4SDimitry 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 }
1774fe013be4SDimitry Andric
isTracked(RegisterRef RR) const1775fe013be4SDimitry Andric bool DataFlowGraph::isTracked(RegisterRef RR) const {
1776fe013be4SDimitry Andric return !disjoint(getPRI().getUnits(RR), TrackedUnits);
1777fe013be4SDimitry Andric }
1778fe013be4SDimitry Andric
hasUntrackedRef(Stmt S,bool IgnoreReserved) const1779fe013be4SDimitry Andric bool DataFlowGraph::hasUntrackedRef(Stmt S, bool IgnoreReserved) const {
1780fe013be4SDimitry Andric SmallVector<MachineOperand *> Ops;
1781fe013be4SDimitry Andric
1782fe013be4SDimitry Andric for (Ref R : S.Addr->members(*this)) {
1783fe013be4SDimitry Andric Ops.push_back(&R.Addr->getOp());
1784fe013be4SDimitry Andric RegisterRef RR = R.Addr->getRegRef(*this);
1785fe013be4SDimitry Andric if (IgnoreReserved && RR.isReg() && ReservedRegs[RR.idx()])
1786fe013be4SDimitry Andric continue;
1787fe013be4SDimitry Andric if (!isTracked(RR))
1788fe013be4SDimitry Andric return true;
1789fe013be4SDimitry Andric }
1790fe013be4SDimitry Andric for (const MachineOperand &Op : S.Addr->getCode()->operands()) {
1791fe013be4SDimitry Andric if (!Op.isReg() && !Op.isRegMask())
1792fe013be4SDimitry Andric continue;
1793*a58f00eaSDimitry Andric if (!llvm::is_contained(Ops, &Op))
1794fe013be4SDimitry Andric return true;
1795fe013be4SDimitry Andric }
1796fe013be4SDimitry Andric return false;
1797fe013be4SDimitry Andric }
1798fe013be4SDimitry Andric
1799fe013be4SDimitry Andric } // end namespace llvm::rdf
1800