mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
[RDF] Create build config
- Add option to ignore reserved registers - Add possibility to track selected registers or register classes only Tracking is done based on register units, so the set of registers to track is translated into a set of register units.
This commit is contained in:
parent
ad1dd78793
commit
39ab9da920
@ -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<const TargetRegisterClass *> RCs) : Classes(RCs) {}
|
||||
Config(ArrayRef<MCPhysReg> Track) : TrackRegs(Track.begin(), Track.end()) {}
|
||||
Config(ArrayRef<RegisterId> Track)
|
||||
: TrackRegs(Track.begin(), Track.end()) {}
|
||||
|
||||
unsigned Options = BuildOptions::None;
|
||||
SmallVector<const TargetRegisterClass *> Classes;
|
||||
std::set<RegisterId> TrackRegs;
|
||||
};
|
||||
|
||||
NodeBase *ptr(NodeId N) const;
|
||||
template <typename T> T ptr(NodeId N) const { //
|
||||
return static_cast<T>(ptr(N));
|
||||
@ -756,7 +771,9 @@ struct DataFlowGraph {
|
||||
// Map: Register (physical or virtual) -> DefStack
|
||||
using DefStackMap = std::unordered_map<RegisterId, DefStack>;
|
||||
|
||||
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 <uint16_t Kind> static bool IsRef(const Node BA) {
|
||||
return BA.Addr->getType() == NodeAttrs::Ref && BA.Addr->getKind() == Kind;
|
||||
@ -882,6 +902,10 @@ private:
|
||||
std::map<MachineBasicBlock *, Block> BlockNodes;
|
||||
// Lane mask map.
|
||||
LaneMaskIndex LMI;
|
||||
|
||||
Config BuildCfg;
|
||||
std::set<unsigned> TrackedUnits;
|
||||
BitVector ReservedRegs;
|
||||
}; // struct DataFlowGraph
|
||||
|
||||
template <typename Predicate>
|
||||
|
@ -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<RegisterId> 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<unsigned, unsigned> 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<MachineOperand *> 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
|
||||
|
Loading…
Reference in New Issue
Block a user