summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2017-04-02 17:24:58 +0000
committerdim <dim@FreeBSD.org>2017-04-02 17:24:58 +0000
commit60b571e49a90d38697b3aca23020d9da42fc7d7f (patch)
tree99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
parentbea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff)
downloadFreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip
FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste): Add WITH_LLD_AS_LD build knob If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not capable of linking the world and kernel, but can self-host and link many substantial applications. GNU ld continues to be used for the world and kernel build, regardless of how this knob is set. It is on by default for arm64, and off for all other CPU architectures. Sponsored by: The FreeBSD Foundation MFC r310840: Reapply 310775, now it also builds correctly if lldb is disabled: Move llvm-objdump from CLANG_EXTRAS to installed by default We currently install three tools from binutils 2.17.50: as, ld, and objdump. Work is underway to migrate to a permissively-licensed tool-chain, with one goal being the retirement of binutils 2.17.50. LLVM's llvm-objdump is intended to be compatible with GNU objdump although it is currently missing some options and may have formatting differences. Enable it by default for testing and further investigation. It may later be changed to install as /usr/bin/objdump, it becomes a fully viable replacement. Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D8879 MFC r312855 (by emaste): Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC Reported by: Dan McGregor <dan.mcgregor usask.ca> MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines Don't check struct rtentry on FreeBSD, it is an internal kernel structure. On other systems it may be API structure for SIOCADDRT/SIOCDELRT. Reviewed by: emaste, dim MFC r314152 (by jkim): Remove an assembler flag, which is redundant since r309124. The upstream took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE. http://llvm.org/viewvc/llvm-project?rev=273500&view=rev Reviewed by: dim MFC r314564: Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 (branches/release_40 296509). The release will follow soon. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Also note that as of 4.0.0, lld should be able to link the base system on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5). Though please be aware that this is work in progress. Release notes for llvm, clang and lld will be available here: <http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html> <http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html> <http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html> Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for their help. Relnotes: yes Exp-run: antoine PR: 215969, 216008 MFC r314708: For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov): [SCEV] limit recursion depth of CompareSCEVComplexity Summary: CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled loop) and runs almost infinite time. Added cache of "equal" SCEV pairs to earlier cutoff of further estimation. Recursion depth limit was also introduced as a parameter. Reviewers: sanjoy Subscribers: mzolotukhin, tstellarAMD, llvm-commits Differential Revision: https://reviews.llvm.org/D26389 This commit is the cause of excessive compile times on skein_block.c (and possibly other files) during kernel builds on amd64. We never saw the problematic behavior described in this upstream commit, so for now it is better to revert it. An upstream bug has been filed here: https://bugs.llvm.org/show_bug.cgi?id=32142 Reported by: mjg MFC r314795: Reapply r287232 from upstream llvm trunk (by Daniil Fukalov): [SCEV] limit recursion depth of CompareSCEVComplexity Summary: CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled loop) and runs almost infinite time. Added cache of "equal" SCEV pairs to earlier cutoff of further estimation. Recursion depth limit was also introduced as a parameter. Reviewers: sanjoy Subscribers: mzolotukhin, tstellarAMD, llvm-commits Differential Revision: https://reviews.llvm.org/D26389 Pull in r296992 from upstream llvm trunk (by Sanjoy Das): [SCEV] Decrease the recursion threshold for CompareValueComplexity Fixes PR32142. r287232 accidentally increased the recursion threshold for CompareValueComplexity from 2 to 32. This change reverses that change by introducing a separate flag for CompareValueComplexity's threshold. The latter revision fixes the excessive compile times for skein_block.c. MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines Unbreak ARMv6 world. The new compiler_rt library imported with clang 4.0.0 have several fatal issues (non-functional __udivsi3 for example) with ARM specific instrict functions. As temporary workaround, until upstream solve these problems, disable all thumb[1][2] related feature. MFC r315016: Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release. We were already very close to the last release candidate, so this is a pretty minor update. Relnotes: yes MFC r316005: Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by Weiming Zhao): builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA. Summary: Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation mode (-mthumb, -marm), it reflect's capability of given CPU. Due to this: - use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB - use '.thumb' directive consistently in all affected files - decorate all thumb functions using DEFINE_COMPILERRT_THUMB_FUNCTION() --------- Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 ! Reviewers: weimingz, rengolin, compnerd Subscribers: aemerson, dim Differential Revision: https://reviews.llvm.org/D30938 Discussed with: mmel
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp538
1 files changed, 314 insertions, 224 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
index 641f014..e74c4bf 100644
--- a/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
+++ b/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
@@ -41,10 +41,10 @@ namespace rdf {
template<>
raw_ostream &operator<< (raw_ostream &OS, const Print<Liveness::RefMap> &P) {
OS << '{';
- for (auto I : P.Obj) {
- OS << ' ' << Print<RegisterRef>(I.first, P.G) << '{';
+ for (auto &I : P.Obj) {
+ OS << ' ' << PrintReg(I.first, &P.G.getTRI()) << '{';
for (auto J = I.second.begin(), E = I.second.end(); J != E; ) {
- OS << Print<NodeId>(*J, P.G);
+ OS << Print<NodeId>(J->first, P.G) << PrintLaneMaskOpt(J->second);
if (++J != E)
OS << ',';
}
@@ -85,10 +85,19 @@ namespace rdf {
// the data-flow.
NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
- NodeAddr<RefNode*> RefA, bool FullChain, const RegisterSet &DefRRs) {
+ NodeAddr<RefNode*> RefA, bool FullChain, const RegisterAggr &DefRRs) {
+ NodeList RDefs; // Return value.
SetVector<NodeId> DefQ;
SetVector<NodeId> Owners;
+ // Dead defs will be treated as if they were live, since they are actually
+ // on the data-flow path. They cannot be ignored because even though they
+ // do not generate meaningful values, they still modify registers.
+
+ // If the reference is undefined, there is nothing to do.
+ if (RefA.Addr->getFlags() & NodeAttrs::Undef)
+ return RDefs;
+
// The initial queue should not have reaching defs for shadows. The
// whole point of a shadow is that it will have a reaching def that
// is not aliased to the reaching defs of the related shadows.
@@ -108,26 +117,24 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
if (TA.Addr->getFlags() & NodeAttrs::PhiRef)
continue;
// Stop at the covering/overwriting def of the initial register reference.
- RegisterRef RR = TA.Addr->getRegRef();
- if (RAI.covers(RR, RefRR)) {
- uint16_t Flags = TA.Addr->getFlags();
- if (!(Flags & NodeAttrs::Preserving))
+ RegisterRef RR = TA.Addr->getRegRef(DFG);
+ if (!DFG.IsPreservingDef(TA))
+ if (RegisterAggr::isCoverOf(RR, RefRR, TRI))
continue;
- }
// Get the next level of reaching defs. This will include multiple
// reaching defs for shadows.
for (auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA))
- if (auto RD = NodeAddr<RefNode*>(S).Addr->getReachingDef())
+ if (NodeId RD = NodeAddr<RefNode*>(S).Addr->getReachingDef())
DefQ.insert(RD);
}
// Remove all non-phi defs that are not aliased to RefRR, and collect
// the owners of the remaining defs.
SetVector<NodeId> Defs;
- for (auto N : DefQ) {
+ for (NodeId N : DefQ) {
auto TA = DFG.addr<DefNode*>(N);
bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef;
- if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef()))
+ if (!IsPhi && !DFG.alias(RefRR, TA.Addr->getRegRef(DFG)))
continue;
Defs.insert(TA.Id);
Owners.insert(TA.Addr->getOwner(DFG).Id);
@@ -156,8 +163,8 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
if (StmtA) {
if (!StmtB) // OB is a phi and phis dominate statements.
return true;
- auto CA = NodeAddr<StmtNode*>(OA).Addr->getCode();
- auto CB = NodeAddr<StmtNode*>(OB).Addr->getCode();
+ MachineInstr *CA = NodeAddr<StmtNode*>(OA).Addr->getCode();
+ MachineInstr *CB = NodeAddr<StmtNode*>(OB).Addr->getCode();
// The order must be linear, so tie-break such equalities.
if (CA == CB)
return A < B;
@@ -189,21 +196,20 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// covered if we added A first, and A would be covered
// if we added B first.
- NodeList RDefs;
- RegisterSet RRs = DefRRs;
+ RegisterAggr RRs(DefRRs);
auto DefInSet = [&Defs] (NodeAddr<RefNode*> TA) -> bool {
return TA.Addr->getKind() == NodeAttrs::Def &&
Defs.count(TA.Id);
};
- for (auto T : Tmp) {
- if (!FullChain && RAI.covers(RRs, RefRR))
+ for (NodeId T : Tmp) {
+ if (!FullChain && RRs.hasCoverOf(RefRR))
break;
auto TA = DFG.addr<InstrNode*>(T);
bool IsPhi = DFG.IsCode<NodeAttrs::Phi>(TA);
NodeList Ds;
for (NodeAddr<DefNode*> DA : TA.Addr->members_if(DefInSet, DFG)) {
- auto QR = DA.Addr->getRegRef();
+ RegisterRef QR = DA.Addr->getRegRef(DFG);
// Add phi defs even if they are covered by subsequent defs. This is
// for cases where the reached use is not covered by any of the defs
// encountered so far: the phi def is needed to expose the liveness
@@ -212,7 +218,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// phi d1<R3>(,d2,), ... Phi def d1 is covered by d2.
// d2<R3>(d1,,u3), ...
// ..., u3<D1>(d2) This use needs to be live on entry.
- if (FullChain || IsPhi || !RAI.covers(RRs, QR))
+ if (FullChain || IsPhi || !RRs.hasCoverOf(QR))
Ds.push_back(DA);
}
RDefs.insert(RDefs.end(), Ds.begin(), Ds.end());
@@ -221,19 +227,17 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// defs to actually define a register.
uint16_t Flags = DA.Addr->getFlags();
if (!FullChain || !(Flags & NodeAttrs::PhiRef))
- if (!(Flags & NodeAttrs::Preserving))
- RRs.insert(DA.Addr->getRegRef());
+ if (!(Flags & NodeAttrs::Preserving)) // Don't care about Undef here.
+ RRs.insert(DA.Addr->getRegRef(DFG));
}
}
- return RDefs;
-}
-
-
-static const RegisterSet NoRegs;
+ auto DeadP = [](const NodeAddr<DefNode*> DA) -> bool {
+ return DA.Addr->getFlags() & NodeAttrs::Dead;
+ };
+ RDefs.resize(std::distance(RDefs.begin(), remove_if(RDefs, DeadP)));
-NodeList Liveness::getAllReachingDefs(NodeAddr<RefNode*> RefA) {
- return getAllReachingDefs(RefA.Addr->getRegRef(), RefA, false, NoRegs);
+ return RDefs;
}
@@ -241,20 +245,20 @@ NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR,
NodeAddr<RefNode*> RefA, NodeSet &Visited, const NodeSet &Defs) {
// Collect all defined registers. Do not consider phis to be defining
// anything, only collect "real" definitions.
- RegisterSet DefRRs;
- for (const auto D : Defs) {
+ RegisterAggr DefRRs(TRI);
+ for (NodeId D : Defs) {
const auto DA = DFG.addr<const DefNode*>(D);
if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef))
- DefRRs.insert(DA.Addr->getRegRef());
+ DefRRs.insert(DA.Addr->getRegRef(DFG));
}
- auto RDs = getAllReachingDefs(RefRR, RefA, true, DefRRs);
+ NodeList RDs = getAllReachingDefs(RefRR, RefA, true, DefRRs);
if (RDs.empty())
return Defs;
// Make a copy of the preexisting definitions and add the newly found ones.
NodeSet TmpDefs = Defs;
- for (auto R : RDs)
+ for (NodeAddr<NodeBase*> R : RDs)
TmpDefs.insert(R.Id);
NodeSet Result = Defs;
@@ -279,39 +283,43 @@ NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR,
NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
- NodeAddr<DefNode*> DefA, const RegisterSet &DefRRs) {
+ NodeAddr<DefNode*> DefA, const RegisterAggr &DefRRs) {
NodeSet Uses;
// If the original register is already covered by all the intervening
// defs, no more uses can be reached.
- if (RAI.covers(DefRRs, RefRR))
+ if (DefRRs.hasCoverOf(RefRR))
return Uses;
// Add all directly reached uses.
- NodeId U = DefA.Addr->getReachedUse();
+ // If the def is dead, it does not provide a value for any use.
+ bool IsDead = DefA.Addr->getFlags() & NodeAttrs::Dead;
+ NodeId U = !IsDead ? DefA.Addr->getReachedUse() : 0;
while (U != 0) {
auto UA = DFG.addr<UseNode*>(U);
- auto UR = UA.Addr->getRegRef();
- if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR))
- Uses.insert(U);
+ if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) {
+ RegisterRef UR = UA.Addr->getRegRef(DFG);
+ if (DFG.alias(RefRR, UR) && !DefRRs.hasCoverOf(UR))
+ Uses.insert(U);
+ }
U = UA.Addr->getSibling();
}
- // Traverse all reached defs.
+ // Traverse all reached defs. This time dead defs cannot be ignored.
for (NodeId D = DefA.Addr->getReachedDef(), NextD; D != 0; D = NextD) {
auto DA = DFG.addr<DefNode*>(D);
NextD = DA.Addr->getSibling();
- auto DR = DA.Addr->getRegRef();
+ RegisterRef DR = DA.Addr->getRegRef(DFG);
// If this def is already covered, it cannot reach anything new.
// Similarly, skip it if it is not aliased to the interesting register.
- if (RAI.covers(DefRRs, DR) || !RAI.alias(RefRR, DR))
+ if (DefRRs.hasCoverOf(DR) || !DFG.alias(RefRR, DR))
continue;
NodeSet T;
- if (DA.Addr->getFlags() & NodeAttrs::Preserving) {
+ if (DFG.IsPreservingDef(DA)) {
// If it is a preserving def, do not update the set of intervening defs.
T = getAllReachedUses(RefRR, DA, DefRRs);
} else {
- RegisterSet NewDefRRs = DefRRs;
+ RegisterAggr NewDefRRs = DefRRs;
NewDefRRs.insert(DR);
T = getAllReachedUses(RefRR, DA, NewDefRRs);
}
@@ -326,42 +334,57 @@ void Liveness::computePhiInfo() {
NodeList Phis;
NodeAddr<FuncNode*> FA = DFG.getFunc();
- auto Blocks = FA.Addr->members(DFG);
+ NodeList Blocks = FA.Addr->members(DFG);
for (NodeAddr<BlockNode*> BA : Blocks) {
auto Ps = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
Phis.insert(Phis.end(), Ps.begin(), Ps.end());
}
// phi use -> (map: reaching phi -> set of registers defined in between)
- std::map<NodeId,std::map<NodeId,RegisterSet>> PhiUp;
+ std::map<NodeId,std::map<NodeId,RegisterAggr>> PhiUp;
std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation.
// Go over all phis.
for (NodeAddr<PhiNode*> PhiA : Phis) {
// Go over all defs and collect the reached uses that are non-phi uses
// (i.e. the "real uses").
- auto &RealUses = RealUseMap[PhiA.Id];
- auto PhiRefs = PhiA.Addr->members(DFG);
+ RefMap &RealUses = RealUseMap[PhiA.Id];
+ NodeList PhiRefs = PhiA.Addr->members(DFG);
// Have a work queue of defs whose reached uses need to be found.
// For each def, add to the queue all reached (non-phi) defs.
SetVector<NodeId> DefQ;
NodeSet PhiDefs;
- for (auto R : PhiRefs) {
+ for (NodeAddr<RefNode*> R : PhiRefs) {
if (!DFG.IsRef<NodeAttrs::Def>(R))
continue;
DefQ.insert(R.Id);
PhiDefs.insert(R.Id);
}
+
+ // Collect the super-set of all possible reached uses. This set will
+ // contain all uses reached from this phi, either directly from the
+ // phi defs, or (recursively) via non-phi defs reached by the phi defs.
+ // This set of uses will later be trimmed to only contain these uses that
+ // are actually reached by the phi defs.
for (unsigned i = 0; i < DefQ.size(); ++i) {
NodeAddr<DefNode*> DA = DFG.addr<DefNode*>(DefQ[i]);
- NodeId UN = DA.Addr->getReachedUse();
+ // Visit all reached uses. Phi defs should not really have the "dead"
+ // flag set, but check it anyway for consistency.
+ bool IsDead = DA.Addr->getFlags() & NodeAttrs::Dead;
+ NodeId UN = !IsDead ? DA.Addr->getReachedUse() : 0;
while (UN != 0) {
NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN);
- if (!(A.Addr->getFlags() & NodeAttrs::PhiRef))
- RealUses[getRestrictedRegRef(A)].insert(A.Id);
+ uint16_t F = A.Addr->getFlags();
+ if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0) {
+ RegisterRef R = DFG.normalizeRef(getRestrictedRegRef(A));
+ RealUses[R.Reg].insert({A.Id,R.Mask});
+ }
UN = A.Addr->getSibling();
}
+ // Visit all reached defs, and add them to the queue. These defs may
+ // override some of the uses collected here, but that will be handled
+ // later.
NodeId DN = DA.Addr->getReachedDef();
while (DN != 0) {
NodeAddr<DefNode*> A = DFG.addr<DefNode*>(DN);
@@ -388,7 +411,7 @@ void Liveness::computePhiInfo() {
// = R1:0 u6 Not reached by d1 (covered collectively
// by d3 and d5), but following reached
// defs and uses from d1 will lead here.
- auto HasDef = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool {
+ auto InPhiDefs = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool {
return PhiDefs.count(DA.Id);
};
for (auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE; ) {
@@ -396,11 +419,14 @@ void Liveness::computePhiInfo() {
// uses of it. For each such use, check if it is reached by this phi,
// i.e. check if the set of its reaching uses intersects the set of
// this phi's defs.
- auto &Uses = UI->second;
+ NodeRefSet &Uses = UI->second;
for (auto I = Uses.begin(), E = Uses.end(); I != E; ) {
- auto UA = DFG.addr<UseNode*>(*I);
- NodeList RDs = getAllReachingDefs(UI->first, UA);
- if (std::any_of(RDs.begin(), RDs.end(), HasDef))
+ auto UA = DFG.addr<UseNode*>(I->first);
+ // Undef flag is checked above.
+ assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0);
+ RegisterRef R(UI->first, I->second);
+ NodeList RDs = getAllReachingDefs(R, UA);
+ if (any_of(RDs, InPhiDefs))
++I;
else
I = Uses.erase(I);
@@ -418,31 +444,50 @@ void Liveness::computePhiInfo() {
// Go over all phi uses and check if the reaching def is another phi.
// Collect the phis that are among the reaching defs of these uses.
- // While traversing the list of reaching defs for each phi use, collect
- // the set of registers defined between this phi (Phi) and the owner phi
+ // While traversing the list of reaching defs for each phi use, accumulate
+ // the set of registers defined between this phi (PhiA) and the owner phi
// of the reaching def.
+ NodeSet SeenUses;
+
for (auto I : PhiRefs) {
- if (!DFG.IsRef<NodeAttrs::Use>(I))
+ if (!DFG.IsRef<NodeAttrs::Use>(I) || SeenUses.count(I.Id))
continue;
NodeAddr<UseNode*> UA = I;
- auto &UpMap = PhiUp[UA.Id];
- RegisterSet DefRRs;
- for (NodeAddr<DefNode*> DA : getAllReachingDefs(UA)) {
- if (DA.Addr->getFlags() & NodeAttrs::PhiRef)
- UpMap[DA.Addr->getOwner(DFG).Id] = DefRRs;
- else
- DefRRs.insert(DA.Addr->getRegRef());
+
+ // Given a phi use UA, traverse all related phi uses (including UA).
+ // The related phi uses may reach different phi nodes or may reach the
+ // same phi node. If multiple uses reach the same phi P, the intervening
+ // defs must be accumulated for all such uses. To group all such uses
+ // into one set, map their node ids to the first use id that reaches P.
+ std::map<NodeId,NodeId> FirstUse; // Phi reached up -> first phi use.
+
+ for (NodeAddr<UseNode*> VA : DFG.getRelatedRefs(PhiA, UA)) {
+ SeenUses.insert(VA.Id);
+ RegisterAggr DefRRs(TRI);
+ for (NodeAddr<DefNode*> DA : getAllReachingDefs(VA)) {
+ if (DA.Addr->getFlags() & NodeAttrs::PhiRef) {
+ NodeId RP = DA.Addr->getOwner(DFG).Id;
+ NodeId FU = FirstUse.insert({RP,VA.Id}).first->second;
+ std::map<NodeId,RegisterAggr> &M = PhiUp[FU];
+ auto F = M.find(RP);
+ if (F == M.end())
+ M.insert(std::make_pair(RP, DefRRs));
+ else
+ F->second.insert(DefRRs);
+ }
+ DefRRs.insert(DA.Addr->getRegRef(DFG));
+ }
}
}
}
if (Trace) {
- dbgs() << "Phi-up-to-phi map:\n";
+ dbgs() << "Phi-up-to-phi map with intervening defs:\n";
for (auto I : PhiUp) {
dbgs() << "phi " << Print<NodeId>(I.first, DFG) << " -> {";
for (auto R : I.second)
dbgs() << ' ' << Print<NodeId>(R.first, DFG)
- << Print<RegisterSet>(R.second, DFG);
+ << Print<RegisterAggr>(R.second, DFG);
dbgs() << " }\n";
}
}
@@ -467,40 +512,50 @@ void Liveness::computePhiInfo() {
//
// When propagating uses up the phi chains, get the all reaching defs
// for a given phi use, and traverse the list until the propagated ref
- // is covered, or until or until reaching the final phi. Only assume
- // that the reference reaches the phi in the latter case.
+ // is covered, or until reaching the final phi. Only assume that the
+ // reference reaches the phi in the latter case.
for (unsigned i = 0; i < PhiUQ.size(); ++i) {
auto PA = DFG.addr<PhiNode*>(PhiUQ[i]);
- auto &RealUses = RealUseMap[PA.Id];
- for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) {
- NodeAddr<UseNode*> UA = U;
- auto &UpPhis = PhiUp[UA.Id];
- for (auto UP : UpPhis) {
+ NodeList PUs = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG);
+ RefMap &RUM = RealUseMap[PA.Id];
+
+ for (NodeAddr<UseNode*> UA : PUs) {
+ std::map<NodeId,RegisterAggr> &PUM = PhiUp[UA.Id];
+ RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(UA));
+ for (const std::pair<NodeId,RegisterAggr> &P : PUM) {
bool Changed = false;
- auto &MidDefs = UP.second;
- // Collect the set UpReached of uses that are reached by the current
- // phi PA, and are not covered by any intervening def between PA and
- // the upward phi UP.
- RegisterSet UpReached;
- for (auto T : RealUses) {
- if (!isRestricted(PA, UA, T.first))
- continue;
- if (!RAI.covers(MidDefs, T.first))
- UpReached.insert(T.first);
- }
- if (UpReached.empty())
+ const RegisterAggr &MidDefs = P.second;
+
+ // Collect the set PropUp of uses that are reached by the current
+ // phi PA, and are not covered by any intervening def between the
+ // currently visited use UA and the the upward phi P.
+
+ if (MidDefs.hasCoverOf(UR))
continue;
- // Update the set PRUs of real uses reached by the upward phi UP with
- // the actual set of uses (UpReached) that the UP phi reaches.
- auto &PRUs = RealUseMap[UP.first];
- for (auto R : UpReached) {
- unsigned Z = PRUs[R].size();
- PRUs[R].insert(RealUses[R].begin(), RealUses[R].end());
- Changed |= (PRUs[R].size() != Z);
+
+ // General algorithm:
+ // for each (R,U) : U is use node of R, U is reached by PA
+ // if MidDefs does not cover (R,U)
+ // then add (R-MidDefs,U) to RealUseMap[P]
+ //
+ for (const std::pair<RegisterId,NodeRefSet> &T : RUM) {
+ RegisterRef R = DFG.restrictRef(RegisterRef(T.first), UR);
+ if (!R)
+ continue;
+ for (std::pair<NodeId,LaneBitmask> V : T.second) {
+ RegisterRef S = DFG.restrictRef(RegisterRef(R.Reg, V.second), R);
+ if (!S)
+ continue;
+ if (RegisterRef SS = MidDefs.clearIn(S)) {
+ NodeRefSet &RS = RealUseMap[P.first][SS.Reg];
+ Changed |= RS.insert({V.first,SS.Mask}).second;
+ }
+ }
}
+
if (Changed)
- PhiUQ.push_back(UP.first);
+ PhiUQ.push_back(P.first);
}
}
}
@@ -512,7 +567,7 @@ void Liveness::computePhiInfo() {
NodeAddr<PhiNode*> PA = DFG.addr<PhiNode*>(I.first);
NodeList Ds = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Def>, DFG);
if (!Ds.empty()) {
- RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef();
+ RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef(DFG);
dbgs() << '<' << Print<RegisterRef>(RR, DFG) << '>';
} else {
dbgs() << "<noreg>";
@@ -540,7 +595,7 @@ void Liveness::computeLiveIns() {
// Compute IDF first, then the inverse.
decltype(IIDF) IDF;
- for (auto &B : MF) {
+ for (MachineBasicBlock &B : MF) {
auto F1 = MDF.find(&B);
if (F1 == MDF.end())
continue;
@@ -562,20 +617,20 @@ void Liveness::computeLiveIns() {
computePhiInfo();
NodeAddr<FuncNode*> FA = DFG.getFunc();
- auto Blocks = FA.Addr->members(DFG);
+ NodeList Blocks = FA.Addr->members(DFG);
// Build the phi live-on-entry map.
for (NodeAddr<BlockNode*> BA : Blocks) {
MachineBasicBlock *MB = BA.Addr->getCode();
- auto &LON = PhiLON[MB];
+ RefMap &LON = PhiLON[MB];
for (auto P : BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG))
- for (auto S : RealUseMap[P.Id])
+ for (const RefMap::value_type &S : RealUseMap[P.Id])
LON[S.first].insert(S.second.begin(), S.second.end());
}
if (Trace) {
dbgs() << "Phi live-on-entry map:\n";
- for (auto I : PhiLON)
+ for (auto &I : PhiLON)
dbgs() << "block #" << I.first->getNumber() << " -> "
<< Print<RefMap>(I.second, DFG) << '\n';
}
@@ -584,33 +639,35 @@ void Liveness::computeLiveIns() {
// "real" uses. Propagate this set backwards into the block predecessors
// through the reaching defs of the corresponding phi uses.
for (NodeAddr<BlockNode*> BA : Blocks) {
- auto Phis = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
+ NodeList Phis = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
for (NodeAddr<PhiNode*> PA : Phis) {
- auto &RUs = RealUseMap[PA.Id];
+ RefMap &RUs = RealUseMap[PA.Id];
if (RUs.empty())
continue;
for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) {
- NodeAddr<PhiUseNode*> UA = U;
- if (UA.Addr->getReachingDef() == 0)
+ NodeAddr<PhiUseNode*> PUA = U;
+ if (PUA.Addr->getReachingDef() == 0)
continue;
// Mark all reached "real" uses of P as live on exit in the
// predecessor.
// Remap all the RUs so that they have a correct reaching def.
- auto PrA = DFG.addr<BlockNode*>(UA.Addr->getPredecessor());
- auto &LOX = PhiLOX[PrA.Addr->getCode()];
- for (auto R : RUs) {
- RegisterRef RR = R.first;
- if (!isRestricted(PA, UA, RR))
- RR = getRestrictedRegRef(UA);
- // The restricted ref may be different from the ref that was
- // accessed in the "real use". This means that this phi use
- // is not the one that carries this reference, so skip it.
- if (!RAI.alias(R.first, RR))
+ auto PrA = DFG.addr<BlockNode*>(PUA.Addr->getPredecessor());
+ RefMap &LOX = PhiLOX[PrA.Addr->getCode()];
+
+ RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(PUA));
+ for (const std::pair<RegisterId,NodeRefSet> &T : RUs) {
+ // Check if T.first aliases UR?
+ LaneBitmask M;
+ for (std::pair<NodeId,LaneBitmask> P : T.second)
+ M |= P.second;
+
+ RegisterRef S = DFG.restrictRef(RegisterRef(T.first, M), UR);
+ if (!S)
continue;
- for (auto D : getAllReachingDefs(RR, UA))
- LOX[RR].insert(D.Id);
+ for (NodeAddr<DefNode*> D : getAllReachingDefs(S, PUA))
+ LOX[S.Reg].insert({D.Id, S.Mask});
}
} // for U : phi uses
} // for P : Phis
@@ -618,7 +675,7 @@ void Liveness::computeLiveIns() {
if (Trace) {
dbgs() << "Phi live-on-exit map:\n";
- for (auto I : PhiLOX)
+ for (auto &I : PhiLOX)
dbgs() << "block #" << I.first->getNumber() << " -> "
<< Print<RefMap>(I.second, DFG) << '\n';
}
@@ -629,19 +686,41 @@ void Liveness::computeLiveIns() {
// Add function live-ins to the live-in set of the function entry block.
auto &EntryIn = LiveMap[&MF.front()];
for (auto I = MRI.livein_begin(), E = MRI.livein_end(); I != E; ++I)
- EntryIn.insert({I->first,0});
+ EntryIn.insert(RegisterRef(I->first));
if (Trace) {
// Dump the liveness map
- for (auto &B : MF) {
- BitVector LV(TRI.getNumRegs());
+ for (MachineBasicBlock &B : MF) {
+ std::vector<RegisterRef> LV;
for (auto I = B.livein_begin(), E = B.livein_end(); I != E; ++I)
- LV.set(I->PhysReg);
+ LV.push_back(RegisterRef(I->PhysReg, I->LaneMask));
+ std::sort(LV.begin(), LV.end());
dbgs() << "BB#" << B.getNumber() << "\t rec = {";
- for (int x = LV.find_first(); x >= 0; x = LV.find_next(x))
- dbgs() << ' ' << Print<RegisterRef>({unsigned(x),0}, DFG);
+ for (auto I : LV)
+ dbgs() << ' ' << Print<RegisterRef>(I, DFG);
dbgs() << " }\n";
- dbgs() << "\tcomp = " << Print<RegisterSet>(LiveMap[&B], DFG) << '\n';
+ //dbgs() << "\tcomp = " << Print<RegisterAggr>(LiveMap[&B], DFG) << '\n';
+
+ LV.clear();
+ for (std::pair<RegisterId,LaneBitmask> P : LiveMap[&B]) {
+ MCSubRegIndexIterator S(P.first, &TRI);
+ if (!S.isValid()) {
+ LV.push_back(RegisterRef(P.first));
+ continue;
+ }
+ do {
+ LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex());
+ if ((M & P.second).any())
+ LV.push_back(RegisterRef(S.getSubReg()));
+ ++S;
+ } while (S.isValid());
+ }
+ std::sort(LV.begin(), LV.end());
+ dbgs() << "\tcomp = {";
+ for (auto I : LV)
+ dbgs() << ' ' << Print<RegisterRef>(I, DFG);
+ dbgs() << " }\n";
+
}
}
}
@@ -658,8 +737,7 @@ void Liveness::resetLiveIns() {
// Add the newly computed live-ins.
auto &LiveIns = LiveMap[&B];
for (auto I : LiveIns) {
- assert(I.Sub == 0);
- B.addLiveIn(I.Reg);
+ B.addLiveIn({MCPhysReg(I.first), I.second});
}
}
}
@@ -672,9 +750,20 @@ void Liveness::resetKills() {
void Liveness::resetKills(MachineBasicBlock *B) {
- auto CopyLiveIns = [] (MachineBasicBlock *B, BitVector &LV) -> void {
- for (auto I = B->livein_begin(), E = B->livein_end(); I != E; ++I)
- LV.set(I->PhysReg);
+ auto CopyLiveIns = [this] (MachineBasicBlock *B, BitVector &LV) -> void {
+ for (auto I : B->liveins()) {
+ MCSubRegIndexIterator S(I.PhysReg, &TRI);
+ if (!S.isValid()) {
+ LV.set(I.PhysReg);
+ continue;
+ }
+ do {
+ LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex());
+ if ((M & I.LaneMask).any())
+ LV.set(S.getSubReg());
+ ++S;
+ } while (S.isValid());
+ }
};
BitVector LiveIn(TRI.getNumRegs()), Live(TRI.getNumRegs());
@@ -724,26 +813,6 @@ void Liveness::resetKills(MachineBasicBlock *B) {
}
-// For shadows, determine if RR is aliased to a reaching def of any other
-// shadow associated with RA. If it is not, then RR is "restricted" to RA,
-// and so it can be considered a value specific to RA. This is important
-// for accurately determining values associated with phi uses.
-// For non-shadows, this function returns "true".
-bool Liveness::isRestricted(NodeAddr<InstrNode*> IA, NodeAddr<RefNode*> RA,
- RegisterRef RR) const {
- NodeId Start = RA.Id;
- for (NodeAddr<RefNode*> TA = DFG.getNextShadow(IA, RA);
- TA.Id != 0 && TA.Id != Start; TA = DFG.getNextShadow(IA, TA)) {
- NodeId RD = TA.Addr->getReachingDef();
- if (RD == 0)
- continue;
- if (RAI.alias(RR, DFG.addr<DefNode*>(RD).Addr->getRegRef()))
- return false;
- }
- return true;
-}
-
-
RegisterRef Liveness::getRestrictedRegRef(NodeAddr<RefNode*> RA) const {
assert(DFG.IsRef<NodeAttrs::Use>(RA));
if (RA.Addr->getFlags() & NodeAttrs::Shadow) {
@@ -751,14 +820,7 @@ RegisterRef Liveness::getRestrictedRegRef(NodeAddr<RefNode*> RA) const {
assert(RD);
RA = DFG.addr<DefNode*>(RD);
}
- return RA.Addr->getRegRef();
-}
-
-
-unsigned Liveness::getPhysReg(RegisterRef RR) const {
- if (!TargetRegisterInfo::isPhysicalRegister(RR.Reg))
- return 0;
- return RR.Sub ? TRI.getSubReg(RR.Reg, RR.Sub) : RR.Reg;
+ return RA.Addr->getRegRef(DFG);
}
@@ -808,77 +870,99 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
}
if (Trace) {
- dbgs() << LLVM_FUNCTION_NAME << " in BB#" << B->getNumber()
- << " after recursion into";
+ dbgs() << "\n-- BB#" << B->getNumber() << ": " << __func__
+ << " after recursion into: {";
for (auto I : *N)
dbgs() << ' ' << I->getBlock()->getNumber();
- dbgs() << "\n LiveIn: " << Print<RefMap>(LiveIn, DFG);
- dbgs() << "\n Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " }\n";
+ dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
- // Add phi uses that are live on exit from this block.
+ // Add reaching defs of phi uses that are live on exit from this block.
RefMap &PUs = PhiLOX[B];
- for (auto S : PUs)
+ for (auto &S : PUs)
LiveIn[S.first].insert(S.second.begin(), S.second.end());
if (Trace) {
dbgs() << "after LOX\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
- // Stop tracking all uses defined in this block: erase those records
- // where the reaching def is located in B and which cover all reached
- // uses.
- auto Copy = LiveIn;
+ // The LiveIn map at this point has all defs that are live-on-exit from B,
+ // as if they were live-on-entry to B. First, we need to filter out all
+ // defs that are present in this block. Then we will add reaching defs of
+ // all upward-exposed uses.
+
+ // To filter out the defs, first make a copy of LiveIn, and then re-populate
+ // LiveIn with the defs that should remain.
+ RefMap LiveInCopy = LiveIn;
LiveIn.clear();
- for (auto I : Copy) {
- auto &Defs = LiveIn[I.first];
- NodeSet Rest;
- for (auto R : I.second) {
- auto DA = DFG.addr<DefNode*>(R);
- RegisterRef DDR = DA.Addr->getRegRef();
+ for (const std::pair<RegisterId,NodeRefSet> &LE : LiveInCopy) {
+ RegisterRef LRef(LE.first);
+ NodeRefSet &NewDefs = LiveIn[LRef.Reg]; // To be filled.
+ const NodeRefSet &OldDefs = LE.second;
+ for (NodeRef OR : OldDefs) {
+ // R is a def node that was live-on-exit
+ auto DA = DFG.addr<DefNode*>(OR.first);
NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG);
NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
- // Defs from a different block need to be preserved. Defs from this
- // block will need to be processed further, except for phi defs, the
- // liveness of which is handled through the PhiLON/PhiLOX maps.
- if (B != BA.Addr->getCode())
- Defs.insert(R);
- else {
- bool IsPreserving = DA.Addr->getFlags() & NodeAttrs::Preserving;
- if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) {
- bool Covering = RAI.covers(DDR, I.first);
- NodeId U = DA.Addr->getReachedUse();
- while (U && Covering) {
- auto DUA = DFG.addr<UseNode*>(U);
- RegisterRef Q = DUA.Addr->getRegRef();
- Covering = RAI.covers(DA.Addr->getRegRef(), Q);
- U = DUA.Addr->getSibling();
- }
- if (!Covering)
- Rest.insert(R);
- }
+ if (B != BA.Addr->getCode()) {
+ // Defs from a different block need to be preserved. Defs from this
+ // block will need to be processed further, except for phi defs, the
+ // liveness of which is handled through the PhiLON/PhiLOX maps.
+ NewDefs.insert(OR);
+ continue;
+ }
+
+ // Defs from this block need to stop the liveness from being
+ // propagated upwards. This only applies to non-preserving defs,
+ // and to the parts of the register actually covered by those defs.
+ // (Note that phi defs should always be preserving.)
+ RegisterAggr RRs(TRI);
+ LRef.Mask = OR.second;
+
+ if (!DFG.IsPreservingDef(DA)) {
+ assert(!(IA.Addr->getFlags() & NodeAttrs::Phi));
+ // DA is a non-phi def that is live-on-exit from this block, and
+ // that is also located in this block. LRef is a register ref
+ // whose use this def reaches. If DA covers LRef, then no part
+ // of LRef is exposed upwards.A
+ if (RRs.insert(DA.Addr->getRegRef(DFG)).hasCoverOf(LRef))
+ continue;
}
- }
- // Non-covering defs from B.
- for (auto R : Rest) {
- auto DA = DFG.addr<DefNode*>(R);
- RegisterRef DRR = DA.Addr->getRegRef();
- RegisterSet RRs;
+ // DA itself was not sufficient to cover LRef. In general, it is
+ // the last in a chain of aliased defs before the exit from this block.
+ // There could be other defs in this block that are a part of that
+ // chain. Check that now: accumulate the registers from these defs,
+ // and if they all together cover LRef, it is not live-on-entry.
for (NodeAddr<DefNode*> TA : getAllReachingDefs(DA)) {
- NodeAddr<InstrNode*> IA = TA.Addr->getOwner(DFG);
- NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
- // Preserving defs do not count towards covering.
+ // DefNode -> InstrNode -> BlockNode.
+ NodeAddr<InstrNode*> ITA = TA.Addr->getOwner(DFG);
+ NodeAddr<BlockNode*> BTA = ITA.Addr->getOwner(DFG);
+ // Reaching defs are ordered in the upward direction.
+ if (BTA.Addr->getCode() != B) {
+ // We have reached past the beginning of B, and the accumulated
+ // registers are not covering LRef. The first def from the
+ // upward chain will be live.
+ // Subtract all accumulated defs (RRs) from LRef.
+ RegisterAggr L(TRI);
+ L.insert(LRef).clear(RRs);
+ assert(!L.empty());
+ NewDefs.insert({TA.Id,L.begin()->second});
+ break;
+ }
+
+ // TA is in B. Only add this def to the accumulated cover if it is
+ // not preserving.
if (!(TA.Addr->getFlags() & NodeAttrs::Preserving))
- RRs.insert(TA.Addr->getRegRef());
- if (BA.Addr->getCode() == B)
- continue;
- if (RAI.covers(RRs, DRR))
+ RRs.insert(TA.Addr->getRegRef(DFG));
+ // If this is enough to cover LRef, then stop.
+ if (RRs.hasCoverOf(LRef))
break;
- Defs.insert(TA.Id);
}
}
}
@@ -888,7 +972,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
if (Trace) {
dbgs() << "after defs in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
// Scan the block for upward-exposed uses and add them to the tracking set.
@@ -897,38 +981,44 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
if (IA.Addr->getKind() != NodeAttrs::Stmt)
continue;
for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) {
- RegisterRef RR = UA.Addr->getRegRef();
- for (auto D : getAllReachingDefs(UA))
+ if (UA.Addr->getFlags() & NodeAttrs::Undef)
+ continue;
+ RegisterRef RR = DFG.normalizeRef(UA.Addr->getRegRef(DFG));
+ for (NodeAddr<DefNode*> D : getAllReachingDefs(UA))
if (getBlockWithRef(D.Id) != B)
- LiveIn[RR].insert(D.Id);
+ LiveIn[RR.Reg].insert({D.Id,RR.Mask});
}
}
if (Trace) {
dbgs() << "after uses in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
// Phi uses should not be propagated up the dominator tree, since they
// are not dominated by their corresponding reaching defs.
- auto &Local = LiveMap[B];
- auto &LON = PhiLON[B];
- for (auto R : LON)
- Local.insert(R.first);
+ RegisterAggr &Local = LiveMap[B];
+ RefMap &LON = PhiLON[B];
+ for (auto &R : LON) {
+ LaneBitmask M;
+ for (auto P : R.second)
+ M |= P.second;
+ Local.insert(RegisterRef(R.first,M));
+ }
if (Trace) {
dbgs() << "after phi uses in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(Local, DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(Local, DFG) << '\n';
}
for (auto C : IIDF[B]) {
- auto &LiveC = LiveMap[C];
- for (auto S : LiveIn)
+ RegisterAggr &LiveC = LiveMap[C];
+ for (const std::pair<RegisterId,NodeRefSet> &S : LiveIn)
for (auto R : S.second)
- if (MDT.properlyDominates(getBlockWithRef(R), C))
- LiveC.insert(S.first);
+ if (MDT.properlyDominates(getBlockWithRef(R.first), C))
+ LiveC.insert(RegisterRef(S.first, R.second));
}
}
OpenPOWER on IntegriCloud