49#include <unordered_map>
57 cl::desc(
"Maximum recursion level"));
63 for (
const auto &
I :
P.Obj) {
64 OS <<
' ' <<
printReg(
I.first, &
P.G.getTRI()) <<
'{';
65 for (
auto J =
I.second.begin(), E =
I.second.end(); J != E;) {
124 auto SNA = DFG.addr<
RefNode *>(Start);
125 if (
NodeId RD = SNA.Addr->getReachingDef())
128 for (
auto S : DFG.getRelatedRefs(RefA.
Addr->getOwner(DFG), RefA))
139 for (
unsigned i = 0; i < DefQ.
size(); ++i) {
140 auto TA = DFG.addr<
DefNode *>(DefQ[i]);
145 if (!DFG.IsPreservingDef(TA))
150 for (
auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA))
165 return BA.
Addr->getCode();
172 std::map<NodeId, NodeAddr<InstrNode *>> Owners;
173 std::map<MachineBasicBlock *, SmallVector<NodeId, 32>> Blocks;
177 if (!IsPhi && !PRI.alias(RefRR, TA.Addr->getRegRef(DFG)))
182 Blocks[
Block(IA)].push_back(IA.Id);
192 if (StmtA && StmtB) {
196 auto FA = OrdMap.
find(InA);
197 if (FA != OrdMap.
end())
198 return FA->second < OrdMap.
find(InB)->second;
200 for (
auto It = BB->
begin(), E = BB->
end(); It != E; ++It) {
209 if (!StmtA && !StmtB) {
220 OrdMap.
insert({&In, ++Pos});
224 std::vector<MachineBasicBlock *> TmpBB;
225 for (
auto &Bucket : Blocks) {
226 TmpBB.push_back(Bucket.first);
227 if (Bucket.second.size() > 2)
228 GetOrder(*Bucket.first);
234 [
this](
auto A,
auto B) {
return MDT.properlyDominates(
A,
B); });
236 std::vector<NodeId> TmpInst;
238 auto &Bucket = Blocks[
MBB];
239 TmpInst.insert(TmpInst.end(), Bucket.rbegin(), Bucket.rend());
281 if (FullChain || IsPhi || !RRs.
hasCoverOf(QR))
288 uint16_t Flags = DA.Addr->getFlags();
291 RRs.
insert(DA.Addr->getRegRef(DFG));
303std::pair<NodeSet, bool>
306 return getAllReachingDefsRecImpl(RefRR, RefA, Visited, Defs, 0,
MaxRecNest);
309std::pair<NodeSet, bool>
312 unsigned Nest,
unsigned MaxNest) {
317 RegisterAggr DefRRs(PRI);
318 for (NodeId
D : Defs) {
319 const auto DA = DFG.
addr<
const DefNode *>(
D);
321 DefRRs.insert(DA.Addr->getRegRef(DFG));
330 for (NodeAddr<NodeBase *> R : RDs)
335 for (NodeAddr<DefNode *> DA : RDs) {
339 NodeAddr<PhiNode *> PA =
DA.Addr->getOwner(DFG);
340 if (!Visited.
insert(PA.Id).second)
343 for (
auto U : PA.Addr->members_if(DFG.IsRef<
NodeAttrs::Use>, DFG)) {
344 const auto &
T = getAllReachingDefsRecImpl(RefRR, U, Visited, TmpDefs,
347 return {
T.first,
false};
348 Result.insert(
T.first.begin(),
T.first.end());
365 return T.Id == FindId;
379 if (!PRI.alias(R.Addr->getRegRef(DFG), RefRR))
400 if ((
N =
N->getIDom()))
401 BA = DFG.findBlock(
N->getBlock());
406 Ins = BA.
Addr->members(DFG);
428 auto UA = DFG.addr<
UseNode *>(U);
431 if (PRI.alias(RefRR, UR) && !DefRRs.
hasCoverOf(UR))
438 for (
NodeId D = DefA.
Addr->getReachedDef(), NextD;
D != 0;
D = NextD) {
440 NextD = DA.Addr->getSibling();
444 if (DefRRs.
hasCoverOf(DR) || !PRI.alias(RefRR, DR))
447 if (DFG.IsPreservingDef(DA)) {
455 Uses.insert(
T.begin(),
T.end());
472 std::map<NodeId, std::map<NodeId, RegisterAggr>> PhiUp;
473 std::vector<NodeId> PhiUQ;
474 std::unordered_map<NodeId, RegisterAggr>
481 RefMap &RealUses = RealUseMap[PhiA.Id];
482 NodeList PhiRefs = PhiA.Addr->members(DFG);
492 DRs.
insert(R.Addr->getRegRef(DFG));
494 PhiDefs.insert(R.Id);
496 PhiDRs.insert(std::make_pair(PhiA.Id, DRs));
503 for (
unsigned i = 0; i < DefQ.
size(); ++i) {
514 RealUses[R.Reg].insert({
A.Id, R.Mask});
516 UN =
A.Addr->getSibling();
521 NodeId DN = DA.Addr->getReachedDef();
524 for (
auto T : DFG.getRelatedRefs(
A.Addr->getOwner(DFG),
A)) {
532 DN =
A.Addr->getSibling();
547 for (
auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE;) {
554 for (std::pair<NodeId, LaneBitmask>
I :
Uses) {
555 auto UA = DFG.addr<
UseNode *>(
I.first);
560 RegisterRef R = PhiDRs.at(PhiA.Id).intersectWith(UseR);
566 if (PhiDefs.count(DA.Id))
568 Covered.
insert(DA.Addr->getRegRef(DFG));
574 UI->second.insert({
I.first, S.
Mask});
577 UI = UI->second.empty() ? RealUses.erase(UI) : std::next(UI);
582 if (!RealUses.empty())
583 PhiUQ.push_back(PhiA.Id);
592 for (
auto I : PhiRefs) {
596 if (PUA.
Addr->getReachingDef() == 0)
605 NodeId RP =
D.Addr->getOwner(DFG).Id;
606 auto [
F, Inserted] = PhiUp[PUA.
Id].try_emplace(RP, DefRRs);
608 F->second.insert(DefRRs);
610 DefRRs.
insert(
D.Addr->getRegRef(DFG));
614 SeenUses.insert(
T.Id);
619 dbgs() <<
"Phi-up-to-phi map with intervening defs:\n";
620 for (
auto I : PhiUp) {
621 dbgs() <<
"phi " <<
Print(
I.first, DFG) <<
" -> {";
622 for (
auto R :
I.second)
654 using RefHash = std::hash<RegisterRef>;
655 using RefEqual = std::equal_to<RegisterRef>;
656 using SubMap = std::unordered_map<RegisterRef, RegisterRef>;
657 std::unordered_map<RegisterAggr, SubMap> Subs;
661 auto F = SM.find(RR);
670 for (
unsigned i = 0; i < PhiUQ.size(); ++i) {
671 auto PA = DFG.addr<
PhiNode *>(PhiUQ[i]);
673 RefMap &RUM = RealUseMap[PA.Id];
676 std::map<NodeId, RegisterAggr> &PUM = PhiUp[UA.Id];
678 for (
const std::pair<const NodeId, RegisterAggr> &
P : PUM) {
687 SubMap &SM = Subs.try_emplace(MidDefs, 1, RefHash(), RefEqual(PRI))
695 for (
const std::pair<const RegisterId, NodeRefSet> &
T : RUM) {
704 for (std::pair<NodeId, LaneBitmask> V :
T.second) {
710 Changed |= RS.insert({V.first, SS.Mask}).second;
716 PhiUQ.push_back(
P.first);
722 dbgs() <<
"Real use map:\n";
723 for (
auto I : RealUseMap) {
733 dbgs() <<
" -> " <<
Print(
I.second, DFG) <<
'\n';
746 NBMap.insert(std::make_pair(
RA.Id, BB));
747 NBMap.insert(std::make_pair(IA.Id, BB));
756 auto F1 = MDF.find(&
B);
760 for (
unsigned i = 0; i < IDFB.
size(); ++i) {
761 auto F2 = MDF.find(IDFB[i]);
767 IDF[&
B].insert(IDFB.
begin(), IDFB.
end());
771 for (
auto *S :
I.second)
784 for (
const RefMap::value_type &S : RealUseMap[
P.Id])
785 LON[S.first].insert(S.second.begin(), S.second.end());
790 dbgs() <<
"Phi live-on-entry map:\n";
791 for (
auto &
I : PhiLON)
792 dbgs() <<
"block #" <<
I.first->getNumber() <<
" -> "
793 <<
Print(
I.second, DFG) <<
'\n';
802 RefMap &RUs = RealUseMap[PA.Id];
807 for (
auto U : PA.Addr->members_if(DFG.IsRef<
NodeAttrs::Use>, DFG)) {
808 if (!SeenUses.insert(U.Id).second)
811 if (PUA.
Addr->getReachingDef() == 0)
825 auto PrA = DFG.addr<
BlockNode *>(PUA.
Addr->getPredecessor());
826 RefMap &LOX = PhiLOX[PrA.Addr->getCode()];
828 for (
const std::pair<const RegisterId, NodeRefSet> &RS : RUs) {
830 for (std::pair<NodeId, LaneBitmask>
P : RS.second) {
839 TA.insert(
D.Addr->getRegRef(DFG)).intersect(S);
841 LOX[S.
Reg].insert({
D.Id, TM});
847 SeenUses.insert(
T.Id);
853 dbgs() <<
"Phi live-on-exit map:\n";
854 for (
auto &
I : PhiLOX)
855 dbgs() <<
"block #" <<
I.first->getNumber() <<
" -> "
856 <<
Print(
I.second, DFG) <<
'\n';
860 traverse(&MF.
front(), LiveIn);
863 LiveMap[&MF.
front()].insert(DFG.getLiveIns());
868 std::vector<RegisterRef> LV;
870 LV.push_back(
RegisterRef(LI.PhysReg, LI.LaneMask));
882 dbgs() <<
"\tcomp = {";
891 for (
auto &
B : DFG.getMF()) {
893 std::vector<MCRegister>
T;
895 T.push_back(LI.PhysReg);
906 for (
auto &
B : DFG.getMF())
912 for (
auto I :
B->liveins()) {
915 LV.set(
I.PhysReg.id());
920 if ((M &
I.LaneMask).any())
927 BitVector LiveIn(TRI.getNumRegs()), Live(TRI.getNumRegs());
928 CopyLiveIns(
B, LiveIn);
929 for (
auto *
SI :
B->successors())
930 CopyLiveIns(
SI, Live);
933 if (
MI.isDebugInstr())
937 for (
auto &
Op :
MI.all_defs()) {
947 for (
MCPhysReg SR : TRI.subregs_inclusive(R))
950 for (
auto &
Op :
MI.all_uses()) {
958 if (!Live[(*AR).id()])
965 for (
MCPhysReg SR : TRI.subregs_inclusive(R))
974 auto F = NBMap.find(RN);
975 if (
F != NBMap.end())
1006 for (
auto *
I : *
N) {
1012 LiveIn[S.first].insert(S.second.begin(), S.second.end());
1017 <<
" after recursion into: {";
1019 dbgs() <<
' ' <<
I->getBlock()->getNumber();
1021 dbgs() <<
" LiveIn: " <<
Print(LiveIn, DFG) <<
'\n';
1022 dbgs() <<
" Local: " <<
Print(LiveMap[
B], DFG) <<
'\n';
1028 LiveIn[S.first].insert(S.second.begin(), S.second.end());
1031 dbgs() <<
"after LOX\n";
1032 dbgs() <<
" LiveIn: " <<
Print(LiveIn, DFG) <<
'\n';
1033 dbgs() <<
" Local: " <<
Print(LiveMap[
B], DFG) <<
'\n';
1043 RefMap LiveInCopy = LiveIn;
1046 for (
const std::pair<const RegisterId, NodeRefSet> &LE : LiveInCopy) {
1047 RegisterRef LRef(
LE.first);
1052 auto DA = DFG.addr<DefNode *>(
OR.first);
1053 NodeAddr<InstrNode *>
IA =
DA.Addr->getOwner(DFG);
1054 NodeAddr<BlockNode *> BA =
IA.Addr->getOwner(DFG);
1055 if (
B != BA.Addr->getCode()) {
1067 RegisterAggr RRs(PRI);
1068 LRef.Mask =
OR.second;
1070 if (!DFG.IsPreservingDef(DA)) {
1076 if (RRs.insert(
DA.Addr->getRegRef(DFG)).hasCoverOf(LRef))
1087 NodeAddr<InstrNode *> ITA =
TA.Addr->getOwner(DFG);
1088 NodeAddr<BlockNode *> BTA = ITA.Addr->getOwner(DFG);
1090 if (BTA.Addr->getCode() !=
B) {
1095 RegisterRef
T = RRs.clearIn(LRef);
1097 NewDefs.insert({
TA.Id,
T.Mask});
1104 RRs.insert(
TA.Addr->getRegRef(DFG));
1106 if (RRs.hasCoverOf(LRef))
1115 dbgs() <<
"after defs in block\n";
1116 dbgs() <<
" LiveIn: " <<
Print(LiveIn, DFG) <<
'\n';
1117 dbgs() <<
" Local: " <<
Print(LiveMap[
B], DFG) <<
'\n';
1121 for (
auto I : DFG.getFunc().Addr->findBlock(
B, DFG).Addr->members(DFG)) {
1122 NodeAddr<InstrNode *>
IA =
I;
1125 for (NodeAddr<UseNode *> UA :
IA.Addr->members_if(DFG.IsUse, DFG)) {
1128 RegisterRef RR = UA.Addr->getRegRef(DFG);
1130 if (getBlockWithRef(
D.Id) !=
B)
1131 LiveIn[RR.Reg].insert({
D.Id, RR.Mask});
1136 dbgs() <<
"after uses in block\n";
1137 dbgs() <<
" LiveIn: " <<
Print(LiveIn, DFG) <<
'\n';
1138 dbgs() <<
" Local: " <<
Print(LiveMap[
B], DFG) <<
'\n';
1143 RegisterAggr &
Local = LiveMap[
B];
1145 for (
auto &R : LON) {
1147 for (
auto P :
R.second)
1149 Local.insert(RegisterRef(
R.first, M));
1153 dbgs() <<
"after phi uses in block\n";
1154 dbgs() <<
" LiveIn: " <<
Print(LiveIn, DFG) <<
'\n';
1158 for (
auto *
C : IIDF[
B]) {
1159 RegisterAggr &LiveC = LiveMap[
C];
1160 for (
const std::pair<const RegisterId, NodeRefSet> &S : LiveIn)
1161 for (
auto R : S.second)
1162 if (MDT.properlyDominates(getBlockWithRef(
R.first),
C))
1163 LiveC.insert(RegisterRef(S.first,
R.second));
1167void Liveness::emptify(RefMap &M) {
1168 for (
auto I =
M.begin(),
E =
M.end();
I !=
E;)
1169 I =
I->second.empty() ?
M.erase(
I) : std::next(
I);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
A common definition of LaneBitmask for use in TableGen and CodeGen.
static cl::opt< unsigned > MaxRecNest("rdf-liveness-max-rec", cl::init(25), cl::Hidden, cl::desc("Maximum recursion level"))
Remove Loads Into Fake Uses
SI optimize exec mask operations pre RA
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
MCRegAliasIterator enumerates all registers aliasing Reg.
Iterator that enumerates the sub-registers of a Reg and the associated sub-register indices.
bool isValid() const
Returns true if this iterator is not yet at the end.
unsigned getSubRegIndex() const
Returns sub-register index of the current sub-register.
MCRegister getSubReg() const
Returns current sub-register.
const MachineBasicBlock & front() const
void insert(iterator MBBI, MachineBasicBlock *MBB)
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
Wrapper class representing virtual and physical registers.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
iterator end()
Get an iterator to the end of the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
NodeAddr< BlockNode * > Block
Print(const T &, const DataFlowGraph &) -> Print< T >
NodeAddr< UseNode * > Use
raw_ostream & operator<<(raw_ostream &OS, const Print< RegisterRef > &P)
std::set< NodeId > NodeSet
SmallVector< Node, 4 > NodeList
This is an optimization pass for GlobalISel generic memory operations.
constexpr from_range_t from_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Pair of physical register and lane mask.
NodeAddr< T > addr(NodeId N) const
NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr< RefNode * > RefA, bool TopShadows, bool FullChain, const RegisterAggr &DefRRs)
std::unordered_set< NodeRef > NodeRefSet
NodeAddr< RefNode * > getNearestAliasedRef(RegisterRef RefRR, NodeAddr< InstrNode * > IA)
Find the nearest ref node aliased to RefRR, going upwards in the data flow, starting from the instruc...
std::pair< NodeSet, bool > getAllReachingDefsRec(RegisterRef RefRR, NodeAddr< RefNode * > RefA, NodeSet &Visited, const NodeSet &Defs)
std::unordered_map< RegisterId, NodeRefSet > RefMap
NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr< DefNode * > DefA, const RegisterAggr &DefRRs)
NodeId getSibling() const
iterator_range< ref_iterator > refs() const
RegisterAggr & insert(RegisterRef RR)
RegisterRef clearIn(RegisterRef RR) const
bool hasAliasOf(RegisterRef RR) const
RegisterRef intersectWith(RegisterRef RR) const
bool hasCoverOf(RegisterRef RR) const
static bool isCoverOf(RegisterRef RA, RegisterRef RB, const PhysicalRegisterInfo &PRI)