diff --git a/llvm/include/llvm/CodeGen/RDFGraph.h b/llvm/include/llvm/CodeGen/RDFGraph.h index b2d6d16e2d5bb..cf7344e8c3e74 100644 --- a/llvm/include/llvm/CodeGen/RDFGraph.h +++ b/llvm/include/llvm/CodeGen/RDFGraph.h @@ -225,6 +225,7 @@ #define LLVM_CODEGEN_RDFGRAPH_H #include "RDFRegisters.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/Support/Allocator.h" @@ -336,6 +337,7 @@ struct BuildOptions { enum : unsigned { None = 0x00, KeepDeadPhis = 0x01, // Do not remove dead phis during build. + OmitReserved = 0x02, // Do not track reserved registers. }; }; @@ -664,6 +666,19 @@ struct DataFlowGraph { const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi); + struct Config { + Config() = default; + Config(unsigned Opts) : Options(Opts) {} + Config(ArrayRef RCs) : Classes(RCs) {} + Config(ArrayRef Track) : TrackRegs(Track.begin(), Track.end()) {} + Config(ArrayRef Track) + : TrackRegs(Track.begin(), Track.end()) {} + + unsigned Options = BuildOptions::None; + SmallVector Classes; + std::set TrackRegs; + }; + NodeBase *ptr(NodeId N) const; template T ptr(NodeId N) const { // return static_cast(ptr(N)); @@ -756,7 +771,9 @@ struct DataFlowGraph { // Map: Register (physical or virtual) -> DefStack using DefStackMap = std::unordered_map; - void build(unsigned Options = BuildOptions::None); + void build(const Config &config); + void build() { build(Config()); } + void pushAllDefs(Instr IA, DefStackMap &DM); void markBlock(NodeId B, DefStackMap &DefM); void releaseBlock(NodeId B, DefStackMap &DefM); @@ -793,6 +810,9 @@ struct DataFlowGraph { removeFromOwner(DA); } + bool isTracked(RegisterRef RR) const; + bool hasUntrackedRef(Stmt S, bool IgnoreReserved = true) const; + // Some useful filters. template static bool IsRef(const Node BA) { return BA.Addr->getType() == NodeAttrs::Ref && BA.Addr->getKind() == Kind; @@ -882,6 +902,10 @@ struct DataFlowGraph { std::map BlockNodes; // Lane mask map. LaneMaskIndex LMI; + + Config BuildCfg; + std::set TrackedUnits; + BitVector ReservedRegs; }; // struct DataFlowGraph template diff --git a/llvm/lib/CodeGen/RDFGraph.cpp b/llvm/lib/CodeGen/RDFGraph.cpp index ece51eae5dd65..abf3b1e6fbb9e 100644 --- a/llvm/lib/CodeGen/RDFGraph.cpp +++ b/llvm/lib/CodeGen/RDFGraph.cpp @@ -855,8 +855,43 @@ Func DataFlowGraph::newFunc(MachineFunction *MF) { } // Build the data flow graph. -void DataFlowGraph::build(unsigned Options) { +void DataFlowGraph::build(const Config &config) { reset(); + BuildCfg = config; + MachineRegisterInfo &MRI = MF.getRegInfo(); + ReservedRegs = MRI.getReservedRegs(); + bool SkipReserved = BuildCfg.Options & BuildOptions::OmitReserved; + + auto Insert = [](auto &Set, auto &&Range) { + Set.insert(Range.begin(), Range.end()); + }; + + if (BuildCfg.TrackRegs.empty()) { + std::set BaseSet; + if (BuildCfg.Classes.empty()) { + // Insert every register. + for (unsigned R = 0, E = getPRI().getTRI().getNumRegs(); R != E; ++R) + BaseSet.insert(R); + } else { + for (const TargetRegisterClass *RC : BuildCfg.Classes) { + for (MCPhysReg R : *RC) + BaseSet.insert(R); + } + } + for (RegisterId R : BaseSet) { + if (SkipReserved && ReservedRegs[R]) + continue; + Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R))); + } + } else { + // Track set in Config overrides everything. + for (unsigned R : BuildCfg.TrackRegs) { + if (SkipReserved && ReservedRegs[R]) + continue; + Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R))); + } + } + TheFunc = newFunc(&MF); if (MF.empty()) @@ -876,7 +911,6 @@ void DataFlowGraph::build(unsigned Options) { NodeList Blocks = TheFunc.Addr->members(*this); // Collect function live-ins and entry block live-ins. - MachineRegisterInfo &MRI = MF.getRegInfo(); MachineBasicBlock &EntryB = *EA.Addr->getCode(); assert(EntryB.pred_empty() && "Function entry block has predecessors"); for (std::pair P : MRI.liveins()) @@ -888,6 +922,8 @@ void DataFlowGraph::build(unsigned Options) { // Add function-entry phi nodes for the live-in registers. for (RegisterRef RR : LiveIns.refs()) { + if (RR.isReg() && !isTracked(RR)) // isReg is likely guaranteed + continue; Phi PA = newPhi(EA); uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; Def DA = newDef(PA, RR, PhiFlags); @@ -913,6 +949,8 @@ void DataFlowGraph::build(unsigned Options) { // Build phi nodes for each live-in. for (RegisterRef RR : EHRegs.refs()) { + if (RR.isReg() && !isTracked(RR)) + continue; Phi PA = newPhi(BA); uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; // Add def: @@ -940,7 +978,7 @@ void DataFlowGraph::build(unsigned Options) { linkBlockRefs(DM, EA); // Finally, remove all unused phi nodes. - if (!(Options & BuildOptions::KeepDeadPhis)) + if (!(BuildCfg.Options & BuildOptions::KeepDeadPhis)) removeUnusedPhis(); } @@ -1024,6 +1062,8 @@ void DataFlowGraph::pushClobbers(Instr IA, DefStackMap &DefM) { DefM[RR.Reg].push(DA); Defined.insert(RR.Reg); for (RegisterId A : getPRI().getAliasSet(RR.Reg)) { + if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A))) + continue; // Check that we don't push the same def twice. assert(A != RR.Reg); if (!Defined.count(A)) @@ -1079,6 +1119,8 @@ void DataFlowGraph::pushDefs(Instr IA, DefStackMap &DefM) { // The def stack traversal in linkNodeUp will check the exact aliasing. DefM[RR.Reg].push(DA); for (RegisterId A : getPRI().getAliasSet(RR.Reg)) { + if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A))) + continue; // Check that we don't push the same def twice. assert(A != RR.Reg); DefM[A].push(DA); @@ -1107,6 +1149,8 @@ NodeList DataFlowGraph::getRelatedRefs(Instr IA, Ref RA) const { void DataFlowGraph::reset() { Memory.clear(); BlockNodes.clear(); + TrackedUnits.clear(); + ReservedRegs.clear(); TheFunc = Func(); } @@ -1245,7 +1289,7 @@ void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) { if (!Op.isReg() || !Op.isDef() || Op.isImplicit()) continue; Register R = Op.getReg(); - if (!R || !R.isPhysical()) + if (!R || !R.isPhysical() || !isTracked(RegisterRef(R))) continue; uint16_t Flags = NodeAttrs::None; if (TOI.isPreserving(In, OpN)) { @@ -1277,9 +1321,12 @@ void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) { SA.Addr->addMember(DA, *this); // Record all clobbered registers in DoneDefs. const uint32_t *RM = Op.getRegMask(); - for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) + for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) { + if (!isTracked(RegisterRef(i))) + continue; if (!(RM[i / 32] & (1u << (i % 32)))) DoneClobbers.set(i); + } } // Process implicit defs, skipping those that have already been added @@ -1289,7 +1336,7 @@ void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) { if (!Op.isReg() || !Op.isDef() || !Op.isImplicit()) continue; Register R = Op.getReg(); - if (!R || !R.isPhysical() || DoneDefs.test(R)) + if (!R || !R.isPhysical() || !isTracked(RegisterRef(R)) || DoneDefs.test(R)) continue; RegisterRef RR = makeRegRef(Op); uint16_t Flags = NodeAttrs::None; @@ -1318,7 +1365,7 @@ void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) { if (!Op.isReg() || !Op.isUse()) continue; Register R = Op.getReg(); - if (!R || !R.isPhysical()) + if (!R || !R.isPhysical() || !isTracked(RegisterRef(R))) continue; uint16_t Flags = NodeAttrs::None; if (Op.isUndef()) @@ -1348,9 +1395,13 @@ void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, Block BA) { // This is done to make sure that each defined reference gets only one // phi node, even if it is defined multiple times. RegisterAggr Defs(getPRI()); - for (Instr IA : BA.Addr->members(*this)) - for (Ref RA : IA.Addr->members_if(IsDef, *this)) - Defs.insert(RA.Addr->getRegRef(*this)); + for (Instr IA : BA.Addr->members(*this)) { + for (Ref RA : IA.Addr->members_if(IsDef, *this)) { + RegisterRef RR = RA.Addr->getRegRef(*this); + if (RR.isReg() && isTracked(RR)) + Defs.insert(RR); + } + } // Calculate the iterated dominance frontier of BB. const MachineDominanceFrontier::DomSetType &DF = DFLoc->second; @@ -1721,4 +1772,28 @@ void DataFlowGraph::unlinkDefDF(Def DA) { } } +bool DataFlowGraph::isTracked(RegisterRef RR) const { + return !disjoint(getPRI().getUnits(RR), TrackedUnits); +} + +bool DataFlowGraph::hasUntrackedRef(Stmt S, bool IgnoreReserved) const { + SmallVector Ops; + + for (Ref R : S.Addr->members(*this)) { + Ops.push_back(&R.Addr->getOp()); + RegisterRef RR = R.Addr->getRegRef(*this); + if (IgnoreReserved && RR.isReg() && ReservedRegs[RR.idx()]) + continue; + if (!isTracked(RR)) + return true; + } + for (const MachineOperand &Op : S.Addr->getCode()->operands()) { + if (!Op.isReg() && !Op.isRegMask()) + continue; + if (llvm::find(Ops, &Op) == Ops.end()) + return true; + } + return false; +} + } // end namespace llvm::rdf