summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp715
1 files changed, 470 insertions, 245 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp b/contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp
index 273d6b7..fa272ea 100644
--- a/contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp
+++ b/contrib/llvm/lib/Target/Hexagon/RDFGraph.cpp
@@ -10,15 +10,31 @@
// Target-independent, SSA-based data flow graph for register data flow (RDF).
//
#include "RDFGraph.h"
-
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominanceFrontier.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/LaneBitmask.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+#include <utility>
+#include <vector>
using namespace llvm;
using namespace rdf;
@@ -28,6 +44,12 @@ using namespace rdf;
namespace llvm {
namespace rdf {
+raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P) {
+ if (!P.Mask.all())
+ OS << ':' << PrintLaneMask(P.Mask);
+ return OS;
+}
+
template<>
raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterRef> &P) {
auto &TRI = P.G.getTRI();
@@ -35,13 +57,7 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterRef> &P) {
OS << TRI.getName(P.Obj.Reg);
else
OS << '#' << P.Obj.Reg;
- if (P.Obj.Sub > 0) {
- OS << ':';
- if (P.Obj.Sub < TRI.getNumSubRegIndices())
- OS << TRI.getSubRegIndexName(P.Obj.Sub);
- else
- OS << '#' << P.Obj.Sub;
- }
+ OS << PrintLaneMaskOpt(P.Obj.Mask);
return OS;
}
@@ -62,6 +78,10 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeId> &P) {
}
break;
case NodeAttrs::Ref:
+ if (Flags & NodeAttrs::Undef)
+ OS << '/';
+ if (Flags & NodeAttrs::Dead)
+ OS << '\\';
if (Flags & NodeAttrs::Preserving)
OS << '+';
if (Flags & NodeAttrs::Clobbering)
@@ -83,14 +103,12 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeId> &P) {
return OS;
}
-namespace {
- void printRefHeader(raw_ostream &OS, const NodeAddr<RefNode*> RA,
- const DataFlowGraph &G) {
- OS << Print<NodeId>(RA.Id, G) << '<'
- << Print<RegisterRef>(RA.Addr->getRegRef(), G) << '>';
- if (RA.Addr->getFlags() & NodeAttrs::Fixed)
- OS << '!';
- }
+static void printRefHeader(raw_ostream &OS, const NodeAddr<RefNode*> RA,
+ const DataFlowGraph &G) {
+ OS << Print<NodeId>(RA.Id, G) << '<'
+ << Print<RegisterRef>(RA.Addr->getRegRef(G), G) << '>';
+ if (RA.Addr->getFlags() & NodeAttrs::Fixed)
+ OS << '!';
}
template<>
@@ -178,9 +196,11 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeSet> &P) {
}
namespace {
+
template <typename T>
struct PrintListV {
PrintListV(const NodeList &L, const DataFlowGraph &G) : List(L), G(G) {}
+
typedef T Type;
const NodeList &List;
const DataFlowGraph &G;
@@ -196,7 +216,8 @@ namespace {
}
return OS;
}
-}
+
+} // end anonymous namespace
template<>
raw_ostream &operator<< (raw_ostream &OS, const Print<NodeAddr<PhiNode*>> &P) {
@@ -208,9 +229,27 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeAddr<PhiNode*>> &P) {
template<>
raw_ostream &operator<< (raw_ostream &OS,
const Print<NodeAddr<StmtNode*>> &P) {
- unsigned Opc = P.Obj.Addr->getCode()->getOpcode();
- OS << Print<NodeId>(P.Obj.Id, P.G) << ": " << P.G.getTII().getName(Opc)
- << " [" << PrintListV<RefNode*>(P.Obj.Addr->members(P.G), P.G) << ']';
+ const MachineInstr &MI = *P.Obj.Addr->getCode();
+ unsigned Opc = MI.getOpcode();
+ OS << Print<NodeId>(P.Obj.Id, P.G) << ": " << P.G.getTII().getName(Opc);
+ // Print the target for calls and branches (for readability).
+ if (MI.isCall() || MI.isBranch()) {
+ MachineInstr::const_mop_iterator T =
+ llvm::find_if(MI.operands(),
+ [] (const MachineOperand &Op) -> bool {
+ return Op.isMBB() || Op.isGlobal() || Op.isSymbol();
+ });
+ if (T != MI.operands_end()) {
+ OS << ' ';
+ if (T->isMBB())
+ OS << "BB#" << T->getMBB()->getNumber();
+ else if (T->isGlobal())
+ OS << T->getGlobal()->getName();
+ else if (T->isSymbol())
+ OS << T->getSymbolName();
+ }
+ }
+ OS << " [" << PrintListV<RefNode*>(P.Obj.Addr->members(P.G), P.G) << ']';
return OS;
}
@@ -234,29 +273,29 @@ raw_ostream &operator<< (raw_ostream &OS,
template<>
raw_ostream &operator<< (raw_ostream &OS,
const Print<NodeAddr<BlockNode*>> &P) {
- auto *BB = P.Obj.Addr->getCode();
+ MachineBasicBlock *BB = P.Obj.Addr->getCode();
unsigned NP = BB->pred_size();
std::vector<int> Ns;
auto PrintBBs = [&OS,&P] (std::vector<int> Ns) -> void {
unsigned N = Ns.size();
- for (auto I : Ns) {
+ for (int I : Ns) {
OS << "BB#" << I;
if (--N)
OS << ", ";
}
};
- OS << Print<NodeId>(P.Obj.Id, P.G) << ": === BB#" << BB->getNumber()
- << " === preds(" << NP << "): ";
- for (auto I : BB->predecessors())
- Ns.push_back(I->getNumber());
+ OS << Print<NodeId>(P.Obj.Id, P.G) << ": --- BB#" << BB->getNumber()
+ << " --- preds(" << NP << "): ";
+ for (MachineBasicBlock *B : BB->predecessors())
+ Ns.push_back(B->getNumber());
PrintBBs(Ns);
unsigned NS = BB->succ_size();
OS << " succs(" << NS << "): ";
Ns.clear();
- for (auto I : BB->successors())
- Ns.push_back(I->getNumber());
+ for (MachineBasicBlock *B : BB->successors())
+ Ns.push_back(B->getNumber());
PrintBBs(Ns);
OS << '\n';
@@ -286,11 +325,17 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterSet> &P) {
}
template<>
+raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterAggr> &P) {
+ P.Obj.print(OS);
+ return OS;
+}
+
+template<>
raw_ostream &operator<< (raw_ostream &OS,
const Print<DataFlowGraph::DefStack> &P) {
for (auto I = P.Obj.top(), E = P.Obj.bottom(); I != E; ) {
OS << Print<NodeId>(I->Id, P.G)
- << '<' << Print<RegisterRef>(I->Addr->getRegRef(), P.G) << '>';
+ << '<' << Print<RegisterRef>(I->Addr->getRegRef(P.G), P.G) << '>';
I.down();
if (I != E)
OS << ' ';
@@ -298,8 +343,8 @@ raw_ostream &operator<< (raw_ostream &OS,
return OS;
}
-} // namespace rdf
-} // namespace llvm
+} // end namespace rdf
+} // end namespace llvm
// Node allocation functions.
//
@@ -361,7 +406,6 @@ void NodeAllocator::clear() {
ActiveEnd = nullptr;
}
-
// Insert node NA after "this" in the circular chain.
void NodeBase::append(NodeAddr<NodeBase*> NA) {
NodeId Nx = Next;
@@ -372,31 +416,31 @@ void NodeBase::append(NodeAddr<NodeBase*> NA) {
}
}
-
// Fundamental node manipulator functions.
// Obtain the register reference from a reference node.
-RegisterRef RefNode::getRegRef() const {
+RegisterRef RefNode::getRegRef(const DataFlowGraph &G) const {
assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
if (NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef)
- return Ref.RR;
+ return G.unpack(Ref.PR);
assert(Ref.Op != nullptr);
- return { Ref.Op->getReg(), Ref.Op->getSubReg() };
+ return G.makeRegRef(Ref.Op->getReg(), Ref.Op->getSubReg());
}
// Set the register reference in the reference node directly (for references
// in phi nodes).
-void RefNode::setRegRef(RegisterRef RR) {
+void RefNode::setRegRef(RegisterRef RR, DataFlowGraph &G) {
assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
assert(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef);
- Ref.RR = RR;
+ Ref.PR = G.pack(RR);
}
// Set the register reference in the reference node based on a machine
// operand (for references in statement nodes).
-void RefNode::setRegRef(MachineOperand *Op) {
+void RefNode::setRegRef(MachineOperand *Op, DataFlowGraph &G) {
assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
assert(!(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef));
+ (void)G;
Ref.Op = Op;
}
@@ -442,7 +486,7 @@ NodeAddr<NodeBase*> CodeNode::getLastMember(const DataFlowGraph &G) const {
// Add node NA at the end of the member list of the given code node.
void CodeNode::addMember(NodeAddr<NodeBase*> NA, const DataFlowGraph &G) {
- auto ML = getLastMember(G);
+ NodeAddr<NodeBase*> ML = getLastMember(G);
if (ML.Id != 0) {
ML.Addr->append(NA);
} else {
@@ -463,7 +507,7 @@ void CodeNode::addMemberAfter(NodeAddr<NodeBase*> MA, NodeAddr<NodeBase*> NA,
// Remove member node NA from the given code node.
void CodeNode::removeMember(NodeAddr<NodeBase*> NA, const DataFlowGraph &G) {
- auto MA = getFirstMember(G);
+ NodeAddr<NodeBase*> MA = getFirstMember(G);
assert(MA.Id != 0);
// Special handling if the member to remove is the first member.
@@ -514,7 +558,7 @@ NodeAddr<NodeBase*> InstrNode::getOwner(const DataFlowGraph &G) {
// Add the phi node PA to the given block node.
void BlockNode::addPhi(NodeAddr<PhiNode*> PA, const DataFlowGraph &G) {
- auto M = getFirstMember(G);
+ NodeAddr<NodeBase*> M = getFirstMember(G);
if (M.Id == 0) {
addMember(PA, G);
return;
@@ -560,115 +604,6 @@ NodeAddr<BlockNode*> FuncNode::getEntryBlock(const DataFlowGraph &G) {
return findBlock(EntryB, G);
}
-
-// Register aliasing information.
-//
-// In theory, the lane information could be used to determine register
-// covering (and aliasing), but depending on the sub-register structure,
-// the lane mask information may be missing. The covering information
-// must be available for this framework to work, so relying solely on
-// the lane data is not sufficient.
-
-// Determine whether RA covers RB.
-bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const {
- if (RA == RB)
- return true;
- if (TargetRegisterInfo::isVirtualRegister(RA.Reg)) {
- assert(TargetRegisterInfo::isVirtualRegister(RB.Reg));
- if (RA.Reg != RB.Reg)
- return false;
- if (RA.Sub == 0)
- return true;
- return TRI.composeSubRegIndices(RA.Sub, RB.Sub) == RA.Sub;
- }
-
- assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg) &&
- TargetRegisterInfo::isPhysicalRegister(RB.Reg));
- unsigned A = RA.Sub != 0 ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg;
- unsigned B = RB.Sub != 0 ? TRI.getSubReg(RB.Reg, RB.Sub) : RB.Reg;
- return TRI.isSubRegister(A, B);
-}
-
-// Determine whether RR is covered by the set of references RRs.
-bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) const {
- if (RRs.count(RR))
- return true;
-
- // For virtual registers, we cannot accurately determine covering based
- // on subregisters. If RR itself is not present in RRs, but it has a sub-
- // register reference, check for the super-register alone. Otherwise,
- // assume non-covering.
- if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) {
- if (RR.Sub != 0)
- return RRs.count({RR.Reg, 0});
- return false;
- }
-
- // If any super-register of RR is present, then RR is covered.
- unsigned Reg = RR.Sub == 0 ? RR.Reg : TRI.getSubReg(RR.Reg, RR.Sub);
- for (MCSuperRegIterator SR(Reg, &TRI); SR.isValid(); ++SR)
- if (RRs.count({*SR, 0}))
- return true;
-
- return false;
-}
-
-// Get the list of references aliased to RR.
-std::vector<RegisterRef> RegisterAliasInfo::getAliasSet(RegisterRef RR) const {
- // Do not include RR in the alias set. For virtual registers return an
- // empty set.
- std::vector<RegisterRef> AS;
- if (TargetRegisterInfo::isVirtualRegister(RR.Reg))
- return AS;
- assert(TargetRegisterInfo::isPhysicalRegister(RR.Reg));
- unsigned R = RR.Reg;
- if (RR.Sub)
- R = TRI.getSubReg(RR.Reg, RR.Sub);
-
- for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI)
- AS.push_back(RegisterRef({*AI, 0}));
- return AS;
-}
-
-// Check whether RA and RB are aliased.
-bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB) const {
- bool VirtA = TargetRegisterInfo::isVirtualRegister(RA.Reg);
- bool VirtB = TargetRegisterInfo::isVirtualRegister(RB.Reg);
- bool PhysA = TargetRegisterInfo::isPhysicalRegister(RA.Reg);
- bool PhysB = TargetRegisterInfo::isPhysicalRegister(RB.Reg);
-
- if (VirtA != VirtB)
- return false;
-
- if (VirtA) {
- if (RA.Reg != RB.Reg)
- return false;
- // RA and RB refer to the same register. If any of them refer to the
- // whole register, they must be aliased.
- if (RA.Sub == 0 || RB.Sub == 0)
- return true;
- unsigned SA = TRI.getSubRegIdxSize(RA.Sub);
- unsigned OA = TRI.getSubRegIdxOffset(RA.Sub);
- unsigned SB = TRI.getSubRegIdxSize(RB.Sub);
- unsigned OB = TRI.getSubRegIdxOffset(RB.Sub);
- if (OA <= OB && OA+SA > OB)
- return true;
- if (OB <= OA && OB+SB > OA)
- return true;
- return false;
- }
-
- assert(PhysA && PhysB);
- (void)PhysA, (void)PhysB;
- unsigned A = RA.Sub ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg;
- unsigned B = RB.Sub ? TRI.getSubReg(RB.Reg, RB.Sub) : RB.Reg;
- for (MCRegAliasIterator I(A, &TRI, true); I.isValid(); ++I)
- if (B == *I)
- return true;
- return false;
-}
-
-
// Target operand information.
//
@@ -695,7 +630,7 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum)
return true;
// Check for a tail call.
if (In.isBranch())
- for (auto &O : In.operands())
+ for (const MachineOperand &O : In.operands())
if (O.isGlobal() || O.isSymbol())
return true;
@@ -708,7 +643,7 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum)
// uses or defs, and those lists do not allow sub-registers.
if (Op.getSubReg() != 0)
return false;
- unsigned Reg = Op.getReg();
+ RegisterId Reg = Op.getReg();
const MCPhysReg *ImpR = Op.isDef() ? D.getImplicitDefs()
: D.getImplicitUses();
if (!ImpR)
@@ -719,6 +654,108 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum)
return false;
}
+RegisterRef RegisterAggr::normalize(RegisterRef RR) const {
+ RegisterId SuperReg = RR.Reg;
+ while (true) {
+ MCSuperRegIterator SR(SuperReg, &TRI, false);
+ if (!SR.isValid())
+ break;
+ SuperReg = *SR;
+ }
+
+ const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg);
+ LaneBitmask Common = RR.Mask & RC.LaneMask;
+ uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg);
+ LaneBitmask SuperMask = TRI.composeSubRegIndexLaneMask(Sub, Common);
+ return RegisterRef(SuperReg, SuperMask);
+}
+
+bool RegisterAggr::hasAliasOf(RegisterRef RR) const {
+ RegisterRef NR = normalize(RR);
+ auto F = Masks.find(NR.Reg);
+ if (F != Masks.end()) {
+ if ((F->second & NR.Mask).any())
+ return true;
+ }
+ if (CheckUnits) {
+ for (MCRegUnitIterator U(RR.Reg, &TRI); U.isValid(); ++U)
+ if (ExpAliasUnits.test(*U))
+ return true;
+ }
+ return false;
+}
+
+bool RegisterAggr::hasCoverOf(RegisterRef RR) const {
+ // Always have a cover for empty lane mask.
+ RegisterRef NR = normalize(RR);
+ if (NR.Mask.none())
+ return true;
+ auto F = Masks.find(NR.Reg);
+ if (F == Masks.end())
+ return false;
+ return (NR.Mask & F->second) == NR.Mask;
+}
+
+RegisterAggr &RegisterAggr::insert(RegisterRef RR) {
+ RegisterRef NR = normalize(RR);
+ auto F = Masks.find(NR.Reg);
+ if (F == Masks.end())
+ Masks.insert({NR.Reg, NR.Mask});
+ else
+ F->second |= NR.Mask;
+
+ // Visit all register units to see if there are any that were created
+ // by explicit aliases. Add those that were to the bit vector.
+ for (MCRegUnitIterator U(RR.Reg, &TRI); U.isValid(); ++U) {
+ MCRegUnitRootIterator R(*U, &TRI);
+ ++R;
+ if (!R.isValid())
+ continue;
+ ExpAliasUnits.set(*U);
+ CheckUnits = true;
+ }
+ return *this;
+}
+
+RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) {
+ for (std::pair<RegisterId,LaneBitmask> P : RG.Masks)
+ insert(RegisterRef(P.first, P.second));
+ return *this;
+}
+
+RegisterAggr &RegisterAggr::clear(RegisterRef RR) {
+ RegisterRef NR = normalize(RR);
+ auto F = Masks.find(NR.Reg);
+ if (F == Masks.end())
+ return *this;
+ LaneBitmask NewM = F->second & ~NR.Mask;
+ if (NewM.none())
+ Masks.erase(F);
+ else
+ F->second = NewM;
+ return *this;
+}
+
+RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) {
+ for (std::pair<RegisterId,LaneBitmask> P : RG.Masks)
+ clear(RegisterRef(P.first, P.second));
+ return *this;
+}
+
+RegisterRef RegisterAggr::clearIn(RegisterRef RR) const {
+ RegisterAggr T(TRI);
+ T.insert(RR).clear(*this);
+ if (T.empty())
+ return RegisterRef();
+ return RegisterRef(T.begin()->first, T.begin()->second);
+}
+
+void RegisterAggr::print(raw_ostream &OS) const {
+ OS << '{';
+ for (auto I : Masks)
+ OS << ' ' << PrintReg(I.first, &TRI) << PrintLaneMaskOpt(I.second);
+ OS << " }";
+}
//
// The data flow graph construction.
@@ -726,13 +763,10 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum)
DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii,
const TargetRegisterInfo &tri, const MachineDominatorTree &mdt,
- const MachineDominanceFrontier &mdf, const RegisterAliasInfo &rai,
- const TargetOperandInfo &toi)
- : TimeG("rdf"), MF(mf), TII(tii), TRI(tri), MDT(mdt), MDF(mdf), RAI(rai),
- TOI(toi) {
+ const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi)
+ : MF(mf), TII(tii), TRI(tri), MDT(mdt), MDF(mdf), TOI(toi) {
}
-
// The implementation of the definition stack.
// Each register reference has its own definition stack. In particular,
// for a register references "Reg" and "Reg:subreg" will each have their
@@ -821,6 +855,32 @@ unsigned DataFlowGraph::DefStack::nextDown(unsigned P) const {
return P;
}
+// Register information.
+
+// Get the list of references aliased to RR. Lane masks are ignored.
+RegisterSet DataFlowGraph::getAliasSet(RegisterId Reg) const {
+ // Do not include RR in the alias set.
+ RegisterSet AS;
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+
+ for (MCRegAliasIterator AI(Reg, &TRI, false); AI.isValid(); ++AI)
+ AS.insert(RegisterRef(*AI));
+ return AS;
+}
+
+RegisterSet DataFlowGraph::getLandingPadLiveIns() const {
+ RegisterSet LR;
+ const Function &F = *MF.getFunction();
+ const Constant *PF = F.hasPersonalityFn() ? F.getPersonalityFn()
+ : nullptr;
+ const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
+ if (RegisterId R = TLI.getExceptionPointerRegister(PF))
+ LR.insert(RegisterRef(R));
+ if (RegisterId R = TLI.getExceptionSelectorRegister(PF))
+ LR.insert(RegisterRef(R));
+ return LR;
+}
+
// Node management functions.
// Get the pointer to the node with the id N.
@@ -864,13 +924,12 @@ NodeAddr<NodeBase*> DataFlowGraph::cloneNode(const NodeAddr<NodeBase*> B) {
return NA;
}
-
// Allocation routines for specific node types/kinds.
NodeAddr<UseNode*> DataFlowGraph::newUse(NodeAddr<InstrNode*> Owner,
MachineOperand &Op, uint16_t Flags) {
NodeAddr<UseNode*> UA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags);
- UA.Addr->setRegRef(&Op);
+ UA.Addr->setRegRef(&Op, *this);
return UA;
}
@@ -878,7 +937,7 @@ NodeAddr<PhiUseNode*> DataFlowGraph::newPhiUse(NodeAddr<PhiNode*> Owner,
RegisterRef RR, NodeAddr<BlockNode*> PredB, uint16_t Flags) {
NodeAddr<PhiUseNode*> PUA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags);
assert(Flags & NodeAttrs::PhiRef);
- PUA.Addr->setRegRef(RR);
+ PUA.Addr->setRegRef(RR, *this);
PUA.Addr->setPredecessor(PredB.Id);
return PUA;
}
@@ -886,7 +945,7 @@ NodeAddr<PhiUseNode*> DataFlowGraph::newPhiUse(NodeAddr<PhiNode*> Owner,
NodeAddr<DefNode*> DataFlowGraph::newDef(NodeAddr<InstrNode*> Owner,
MachineOperand &Op, uint16_t Flags) {
NodeAddr<DefNode*> DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags);
- DA.Addr->setRegRef(&Op);
+ DA.Addr->setRegRef(&Op, *this);
return DA;
}
@@ -894,7 +953,7 @@ NodeAddr<DefNode*> DataFlowGraph::newDef(NodeAddr<InstrNode*> Owner,
RegisterRef RR, uint16_t Flags) {
NodeAddr<DefNode*> DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags);
assert(Flags & NodeAttrs::PhiRef);
- DA.Addr->setRegRef(RR);
+ DA.Addr->setRegRef(RR, *this);
return DA;
}
@@ -934,17 +993,20 @@ void DataFlowGraph::build(unsigned Options) {
if (MF.empty())
return;
- for (auto &B : MF) {
- auto BA = newBlock(Func, &B);
- for (auto &I : B) {
+ for (MachineBasicBlock &B : MF) {
+ NodeAddr<BlockNode*> BA = newBlock(Func, &B);
+ BlockNodes.insert(std::make_pair(&B, BA));
+ for (MachineInstr &I : B) {
if (I.isDebugValue())
continue;
buildStmt(BA, I);
}
}
- // Collect information about block references.
NodeAddr<BlockNode*> EA = Func.Addr->getEntryBlock(*this);
+ NodeList Blocks = Func.Addr->members(*this);
+
+ // Collect information about block references.
BlockRefsMap RefM;
buildBlockRefs(EA, RefM);
@@ -952,16 +1014,48 @@ void DataFlowGraph::build(unsigned Options) {
MachineRegisterInfo &MRI = MF.getRegInfo();
for (auto I = MRI.livein_begin(), E = MRI.livein_end(); I != E; ++I) {
NodeAddr<PhiNode*> PA = newPhi(EA);
- RegisterRef RR = { I->first, 0 };
+ RegisterRef RR = RegisterRef(I->first);
uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
NodeAddr<DefNode*> DA = newDef(PA, RR, PhiFlags);
PA.Addr->addMember(DA, *this);
}
+ // Add phis for landing pads.
+ // Landing pads, unlike usual backs blocks, are not entered through
+ // branches in the program, or fall-throughs from other blocks. They
+ // are entered from the exception handling runtime and target's ABI
+ // may define certain registers as defined on entry to such a block.
+ RegisterSet EHRegs = getLandingPadLiveIns();
+ if (!EHRegs.empty()) {
+ for (NodeAddr<BlockNode*> BA : Blocks) {
+ const MachineBasicBlock &B = *BA.Addr->getCode();
+ if (!B.isEHPad())
+ continue;
+
+ // Prepare a list of NodeIds of the block's predecessors.
+ NodeList Preds;
+ for (MachineBasicBlock *PB : B.predecessors())
+ Preds.push_back(findBlock(PB));
+
+ // Build phi nodes for each live-in.
+ for (RegisterRef RR : EHRegs) {
+ NodeAddr<PhiNode*> PA = newPhi(BA);
+ uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
+ // Add def:
+ NodeAddr<DefNode*> DA = newDef(PA, RR, PhiFlags);
+ PA.Addr->addMember(DA, *this);
+ // Add uses (no reaching defs for phi uses):
+ for (NodeAddr<BlockNode*> PBA : Preds) {
+ NodeAddr<PhiUseNode*> PUA = newPhiUse(PA, RR, PBA);
+ PA.Addr->addMember(PUA, *this);
+ }
+ }
+ }
+ }
+
// Build a map "PhiM" which will contain, for each block, the set
// of references that will require phi definitions in that block.
BlockRefsMap PhiM;
- auto Blocks = Func.Addr->members(*this);
for (NodeAddr<BlockNode*> BA : Blocks)
recordDefsForDF(PhiM, RefM, BA);
for (NodeAddr<BlockNode*> BA : Blocks)
@@ -976,6 +1070,47 @@ void DataFlowGraph::build(unsigned Options) {
removeUnusedPhis();
}
+RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const {
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+ if (Sub != 0)
+ Reg = TRI.getSubReg(Reg, Sub);
+ return RegisterRef(Reg);
+}
+
+RegisterRef DataFlowGraph::normalizeRef(RegisterRef RR) const {
+ // FIXME copied from RegisterAggr
+ RegisterId SuperReg = RR.Reg;
+ while (true) {
+ MCSuperRegIterator SR(SuperReg, &TRI, false);
+ if (!SR.isValid())
+ break;
+ SuperReg = *SR;
+ }
+
+ uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg);
+ const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg);
+ LaneBitmask SuperMask = RR.Mask &
+ TRI.composeSubRegIndexLaneMask(Sub, RC.LaneMask);
+ return RegisterRef(SuperReg, SuperMask);
+}
+
+RegisterRef DataFlowGraph::restrictRef(RegisterRef AR, RegisterRef BR) const {
+ if (AR.Reg == BR.Reg) {
+ LaneBitmask M = AR.Mask & BR.Mask;
+ return M.any() ? RegisterRef(AR.Reg, M) : RegisterRef();
+ }
+#ifndef NDEBUG
+ RegisterRef NAR = normalizeRef(AR);
+ RegisterRef NBR = normalizeRef(BR);
+ assert(NAR.Reg != NBR.Reg);
+#endif
+ // This isn't strictly correct, because the overlap may happen in the
+ // part masked out.
+ if (TRI.regsOverlap(AR.Reg, BR.Reg))
+ return AR;
+ return RegisterRef();
+}
+
// For each stack in the map DefM, push the delimiter for block B on it.
void DataFlowGraph::markBlock(NodeId B, DefStackMap &DefM) {
// Push block delimiters.
@@ -1024,28 +1159,31 @@ void DataFlowGraph::pushDefs(NodeAddr<InstrNode*> IA, DefStackMap &DefM) {
for (NodeAddr<DefNode*> DA : Defs) {
if (Visited.count(DA.Id))
continue;
+
NodeList Rel = getRelatedRefs(IA, DA);
NodeAddr<DefNode*> PDA = Rel.front();
- // Push the definition on the stack for the register and all aliases.
- RegisterRef RR = PDA.Addr->getRegRef();
+ RegisterRef RR = PDA.Addr->getRegRef(*this);
#ifndef NDEBUG
// Assert if the register is defined in two or more unrelated defs.
// This could happen if there are two or more def operands defining it.
if (!Defined.insert(RR).second) {
- auto *MI = NodeAddr<StmtNode*>(IA).Addr->getCode();
+ MachineInstr *MI = NodeAddr<StmtNode*>(IA).Addr->getCode();
dbgs() << "Multiple definitions of register: "
<< Print<RegisterRef>(RR, *this) << " in\n " << *MI
<< "in BB#" << MI->getParent()->getNumber() << '\n';
llvm_unreachable(nullptr);
}
#endif
- DefM[RR].push(DA);
- for (auto A : RAI.getAliasSet(RR)) {
+ // Push the definition on the stack for the register and all aliases.
+ // The def stack traversal in linkNodeUp will check the exact aliasing.
+ DefM[RR.Reg].push(DA);
+ for (RegisterRef A : getAliasSet(RR.Reg /*FIXME? use RegisterRef*/)) {
+ // Check that we don't push the same def twice.
assert(A != RR);
- DefM[A].push(DA);
+ DefM[A.Reg].push(DA);
}
// Mark all the related defs as visited.
- for (auto T : Rel)
+ for (NodeAddr<NodeBase*> T : Rel)
Visited.insert(T.Id);
}
}
@@ -1065,14 +1203,66 @@ NodeList DataFlowGraph::getRelatedRefs(NodeAddr<InstrNode*> IA,
return Refs;
}
+// Return true if RA and RB overlap, false otherwise.
+bool DataFlowGraph::alias(RegisterRef RA, RegisterRef RB) const {
+ assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg));
+ assert(TargetRegisterInfo::isPhysicalRegister(RB.Reg));
+
+ MCRegUnitMaskIterator UMA(RA.Reg, &TRI);
+ MCRegUnitMaskIterator UMB(RB.Reg, &TRI);
+ // Reg units are returned in the numerical order.
+ while (UMA.isValid() && UMB.isValid()) {
+ std::pair<uint32_t,LaneBitmask> PA = *UMA;
+ std::pair<uint32_t,LaneBitmask> PB = *UMB;
+ if (PA.first == PB.first) {
+ // Lane mask of 0 (given by the iterator) should be treated as "full".
+ // This can happen when the register has only one unit, or when the
+ // unit corresponds to explicit aliasing. In such cases, the lane mask
+ // from RegisterRef should be ignored.
+ if (PA.second.none() || PB.second.none())
+ return true;
+
+ // At this point the common unit corresponds to a subregister. The lane
+ // masks correspond to the lane mask of that unit within the original
+ // register, for example assuming register quadruple q0 = r3:0, and
+ // a register pair d1 = r3:2, the lane mask of r2 in q0 may be 0b0100,
+ // while the lane mask of r2 in d1 may be 0b0001.
+ LaneBitmask LA = PA.second & RA.Mask;
+ LaneBitmask LB = PB.second & RB.Mask;
+ if (LA.any() && LB.any()) {
+ unsigned Root = *MCRegUnitRootIterator(PA.first, &TRI);
+ // If register units were guaranteed to only have 1 bit in any lane
+ // mask, the code below would not be necessary. This is because LA
+ // and LB would have at most 1 bit set each, and that bit would be
+ // guaranteed to correspond to the given register unit.
+ uint32_t SubA = TRI.getSubRegIndex(RA.Reg, Root);
+ uint32_t SubB = TRI.getSubRegIndex(RB.Reg, Root);
+ const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(Root);
+ LaneBitmask MaskA = TRI.reverseComposeSubRegIndexLaneMask(SubA, LA);
+ LaneBitmask MaskB = TRI.reverseComposeSubRegIndexLaneMask(SubB, LB);
+ if ((MaskA & MaskB & RC.LaneMask).any())
+ return true;
+ }
+
+ ++UMA;
+ ++UMB;
+ continue;
+ }
+ if (PA.first < PB.first)
+ ++UMA;
+ else if (PB.first < PA.first)
+ ++UMB;
+ }
+ return false;
+}
// Clear all information in the graph.
void DataFlowGraph::reset() {
Memory.clear();
+ BlockNodes.clear();
Func = NodeAddr<FuncNode*>();
}
-
// Return the next reference node in the instruction node IA that is related
// to RA. Conceptually, two reference nodes are related if they refer to the
// same instance of a register access, but differ in flags or other minor
@@ -1083,10 +1273,10 @@ NodeAddr<RefNode*> DataFlowGraph::getNextRelated(NodeAddr<InstrNode*> IA,
NodeAddr<RefNode*> RA) const {
assert(IA.Id != 0 && RA.Id != 0);
- auto Related = [RA](NodeAddr<RefNode*> TA) -> bool {
+ auto Related = [this,RA](NodeAddr<RefNode*> TA) -> bool {
if (TA.Addr->getKind() != RA.Addr->getKind())
return false;
- if (TA.Addr->getRegRef() != RA.Addr->getRegRef())
+ if (TA.Addr->getRegRef(*this) != RA.Addr->getRegRef(*this))
return false;
return true;
};
@@ -1105,7 +1295,7 @@ NodeAddr<RefNode*> DataFlowGraph::getNextRelated(NodeAddr<InstrNode*> IA,
return TUA.Addr->getPredecessor() == RUA.Addr->getPredecessor();
};
- RegisterRef RR = RA.Addr->getRegRef();
+ RegisterRef RR = RA.Addr->getRegRef(*this);
if (IA.Addr->getKind() == NodeAttrs::Stmt)
return RA.Addr->getNextRef(RR, RelatedStmt, true, *this);
return RA.Addr->getNextRef(RR, RelatedPhi, true, *this);
@@ -1174,31 +1364,45 @@ NodeAddr<RefNode*> DataFlowGraph::getNextShadow(NodeAddr<InstrNode*> IA,
// Create a new statement node in the block node BA that corresponds to
// the machine instruction MI.
void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
- auto SA = newStmt(BA, &In);
+ NodeAddr<StmtNode*> SA = newStmt(BA, &In);
auto isCall = [] (const MachineInstr &In) -> bool {
if (In.isCall())
return true;
// Is tail call?
if (In.isBranch())
- for (auto &Op : In.operands())
+ for (const MachineOperand &Op : In.operands())
if (Op.isGlobal() || Op.isSymbol())
return true;
return false;
};
+ auto isDefUndef = [this] (const MachineInstr &In, RegisterRef DR) -> bool {
+ // This instruction defines DR. Check if there is a use operand that
+ // would make DR live on entry to the instruction.
+ for (const MachineOperand &UseOp : In.operands()) {
+ if (!UseOp.isReg() || !UseOp.isUse() || UseOp.isUndef())
+ continue;
+ RegisterRef UR = makeRegRef(UseOp.getReg(), UseOp.getSubReg());
+ if (alias(DR, UR))
+ return false;
+ }
+ return true;
+ };
+
// Collect a set of registers that this instruction implicitly uses
// or defines. Implicit operands from an instruction will be ignored
// unless they are listed here.
RegisterSet ImpUses, ImpDefs;
if (const uint16_t *ImpD = In.getDesc().getImplicitDefs())
while (uint16_t R = *ImpD++)
- ImpDefs.insert({R, 0});
+ ImpDefs.insert(RegisterRef(R));
if (const uint16_t *ImpU = In.getDesc().getImplicitUses())
while (uint16_t R = *ImpU++)
- ImpUses.insert({R, 0});
+ ImpUses.insert(RegisterRef(R));
- bool NeedsImplicit = isCall(In) || In.isInlineAsm() || In.isReturn();
+ bool IsCall = isCall(In);
+ bool NeedsImplicit = IsCall || In.isInlineAsm() || In.isReturn();
bool IsPredicated = TII.isPredicated(In);
unsigned NumOps = In.getNumOperands();
@@ -1212,14 +1416,20 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isDef() || Op.isImplicit())
continue;
- RegisterRef RR = { Op.getReg(), Op.getSubReg() };
+ RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
uint16_t Flags = NodeAttrs::None;
- if (TOI.isPreserving(In, OpN))
+ if (TOI.isPreserving(In, OpN)) {
Flags |= NodeAttrs::Preserving;
+ // If the def is preserving, check if it is also undefined.
+ if (isDefUndef(In, RR))
+ Flags |= NodeAttrs::Undef;
+ }
if (TOI.isClobbering(In, OpN))
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
+ if (IsCall && Op.isDead())
+ Flags |= NodeAttrs::Dead;
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
DoneDefs.insert(RR);
@@ -1231,18 +1441,24 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isDef() || !Op.isImplicit())
continue;
- RegisterRef RR = { Op.getReg(), Op.getSubReg() };
+ RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
if (!NeedsImplicit && !ImpDefs.count(RR))
continue;
if (DoneDefs.count(RR))
continue;
uint16_t Flags = NodeAttrs::None;
- if (TOI.isPreserving(In, OpN))
+ if (TOI.isPreserving(In, OpN)) {
Flags |= NodeAttrs::Preserving;
+ // If the def is preserving, check if it is also undefined.
+ if (isDefUndef(In, RR))
+ Flags |= NodeAttrs::Undef;
+ }
if (TOI.isClobbering(In, OpN))
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
+ if (IsCall && Op.isDead())
+ Flags |= NodeAttrs::Dead;
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
DoneDefs.insert(RR);
@@ -1252,7 +1468,7 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isUse())
continue;
- RegisterRef RR = { Op.getReg(), Op.getSubReg() };
+ RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
// Add implicit uses on return and call instructions, and on predicated
// instructions regardless of whether or not they appear in the instruction
// descriptor's list.
@@ -1261,6 +1477,8 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
if (Implicit && !TakeImplicit && !ImpUses.count(RR))
continue;
uint16_t Flags = NodeAttrs::None;
+ if (Op.isUndef())
+ Flags |= NodeAttrs::Undef;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
NodeAddr<UseNode*> UA = newUse(SA, Op, Flags);
@@ -1272,20 +1490,20 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
// that block, and from all blocks dominated by it.
void DataFlowGraph::buildBlockRefs(NodeAddr<BlockNode*> BA,
BlockRefsMap &RefM) {
- auto &Refs = RefM[BA.Id];
+ RegisterSet &Refs = RefM[BA.Id];
MachineDomTreeNode *N = MDT.getNode(BA.Addr->getCode());
assert(N);
for (auto I : *N) {
MachineBasicBlock *SB = I->getBlock();
- auto SBA = Func.Addr->findBlock(SB, *this);
+ NodeAddr<BlockNode*> SBA = findBlock(SB);
buildBlockRefs(SBA, RefM);
- const auto &SRs = RefM[SBA.Id];
- Refs.insert(SRs.begin(), SRs.end());
+ const RegisterSet &RefsS = RefM[SBA.Id];
+ Refs.insert(RefsS.begin(), RefsS.end());
}
for (NodeAddr<InstrNode*> IA : BA.Addr->members(*this))
for (NodeAddr<RefNode*> RA : IA.Addr->members(*this))
- Refs.insert(RA.Addr->getRegRef());
+ Refs.insert(RA.Addr->getRegRef(*this));
}
// Scan all defs in the block node BA and record in PhiM the locations of
@@ -1307,17 +1525,11 @@ void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, BlockRefsMap &RefM,
// This is done to make sure that each defined reference gets only one
// phi node, even if it is defined multiple times.
RegisterSet Defs;
- for (auto I : BA.Addr->members(*this)) {
- assert(I.Addr->getType() == NodeAttrs::Code);
- assert(I.Addr->getKind() == NodeAttrs::Phi ||
- I.Addr->getKind() == NodeAttrs::Stmt);
- NodeAddr<InstrNode*> IA = I;
+ for (NodeAddr<InstrNode*> IA : BA.Addr->members(*this))
for (NodeAddr<RefNode*> RA : IA.Addr->members_if(IsDef, *this))
- Defs.insert(RA.Addr->getRegRef());
- }
+ Defs.insert(RA.Addr->getRegRef(*this));
- // Finally, add the set of defs to each block in the iterated dominance
- // frontier.
+ // Calculate the iterated dominance frontier of BB.
const MachineDominanceFrontier::DomSetType &DF = DFLoc->second;
SetVector<MachineBasicBlock*> IDF(DF.begin(), DF.end());
for (unsigned i = 0; i < IDF.size(); ++i) {
@@ -1329,13 +1541,15 @@ void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, BlockRefsMap &RefM,
// Get the register references that are reachable from this block.
RegisterSet &Refs = RefM[BA.Id];
for (auto DB : IDF) {
- auto DBA = Func.Addr->findBlock(DB, *this);
- const auto &Rs = RefM[DBA.Id];
- Refs.insert(Rs.begin(), Rs.end());
+ NodeAddr<BlockNode*> DBA = findBlock(DB);
+ const RegisterSet &RefsD = RefM[DBA.Id];
+ Refs.insert(RefsD.begin(), RefsD.end());
}
+ // Finally, add the set of defs to each block in the iterated dominance
+ // frontier.
for (auto DB : IDF) {
- auto DBA = Func.Addr->findBlock(DB, *this);
+ NodeAddr<BlockNode*> DBA = findBlock(DB);
PhiM[DBA.Id].insert(Defs.begin(), Defs.end());
}
}
@@ -1355,19 +1569,19 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM,
// are not covered by another ref (i.e. maximal with respect to covering).
auto MaxCoverIn = [this] (RegisterRef RR, RegisterSet &RRs) -> RegisterRef {
- for (auto I : RRs)
- if (I != RR && RAI.covers(I, RR))
+ for (RegisterRef I : RRs)
+ if (I != RR && RegisterAggr::isCoverOf(I, RR, TRI))
RR = I;
return RR;
};
RegisterSet MaxDF;
- for (auto I : HasDF->second)
+ for (RegisterRef I : HasDF->second)
MaxDF.insert(MaxCoverIn(I, HasDF->second));
std::vector<RegisterRef> MaxRefs;
- auto &RefB = RefM[BA.Id];
- for (auto I : MaxDF)
+ RegisterSet &RefB = RefM[BA.Id];
+ for (RegisterRef I : MaxDF)
MaxRefs.push_back(MaxCoverIn(I, RefB));
// Now, for each R in MaxRefs, get the alias closure of R. If the closure
@@ -1382,19 +1596,17 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM,
auto Aliased = [this,&MaxRefs](RegisterRef RR,
std::vector<unsigned> &Closure) -> bool {
- for (auto I : Closure)
- if (RAI.alias(RR, MaxRefs[I]))
+ for (unsigned I : Closure)
+ if (alias(RR, MaxRefs[I]))
return true;
return false;
};
// Prepare a list of NodeIds of the block's predecessors.
- std::vector<NodeId> PredList;
+ NodeList Preds;
const MachineBasicBlock *MBB = BA.Addr->getCode();
- for (auto PB : MBB->predecessors()) {
- auto B = Func.Addr->findBlock(PB, *this);
- PredList.push_back(B.Id);
- }
+ for (MachineBasicBlock *PB : MBB->predecessors())
+ Preds.push_back(findBlock(PB));
while (!MaxRefs.empty()) {
// Put the first element in the closure, and then add all subsequent
@@ -1418,8 +1630,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM,
PA.Addr->addMember(DA, *this);
}
// Add phi uses.
- for (auto P : PredList) {
- auto PBA = addr<BlockNode*>(P);
+ for (NodeAddr<BlockNode*> PBA : Preds) {
for (unsigned X = 0; X != CS; ++X) {
RegisterRef RR = MaxRefs[ClosureIdx[X]];
NodeAddr<PhiUseNode*> PUA = newPhiUse(PA, RR, PBA);
@@ -1449,7 +1660,7 @@ void DataFlowGraph::removeUnusedPhis() {
}
static auto HasUsedDef = [](NodeList &Ms) -> bool {
- for (auto M : Ms) {
+ for (NodeAddr<NodeBase*> M : Ms) {
if (M.Addr->getKind() != NodeAttrs::Def)
continue;
NodeAddr<DefNode*> DA = M;
@@ -1493,25 +1704,25 @@ void DataFlowGraph::linkRefUp(NodeAddr<InstrNode*> IA, NodeAddr<T> TA,
DefStack &DS) {
if (DS.empty())
return;
- RegisterRef RR = TA.Addr->getRegRef();
+ RegisterRef RR = TA.Addr->getRegRef(*this);
NodeAddr<T> TAP;
// References from the def stack that have been examined so far.
- RegisterSet Defs;
+ RegisterAggr Defs(TRI);
for (auto I = DS.top(), E = DS.bottom(); I != E; I.down()) {
- RegisterRef QR = I->Addr->getRegRef();
- auto AliasQR = [QR,this] (RegisterRef RR) -> bool {
- return RAI.alias(QR, RR);
- };
- bool PrecUp = RAI.covers(QR, RR);
+ RegisterRef QR = I->Addr->getRegRef(*this);
+
// Skip all defs that are aliased to any of the defs that we have already
- // seen. If we encounter a covering def, stop the stack traversal early.
- if (std::any_of(Defs.begin(), Defs.end(), AliasQR)) {
- if (PrecUp)
+ // seen. If this completes a cover of RR, stop the stack traversal.
+ bool Alias = Defs.hasAliasOf(QR);
+ bool Cover = Defs.insert(QR).hasCoverOf(RR);
+ if (Alias) {
+ if (Cover)
break;
continue;
}
+
// The reaching def.
NodeAddr<DefNode*> RDA = *I;
@@ -1527,27 +1738,29 @@ void DataFlowGraph::linkRefUp(NodeAddr<InstrNode*> IA, NodeAddr<T> TA,
// Create the link.
TAP.Addr->linkToDef(TAP.Id, RDA);
- if (PrecUp)
+ if (Cover)
break;
- Defs.insert(QR);
}
}
// Create data-flow links for all reference nodes in the statement node SA.
void DataFlowGraph::linkStmtRefs(DefStackMap &DefM, NodeAddr<StmtNode*> SA) {
+#ifndef NDEBUG
RegisterSet Defs;
+#endif
// Link all nodes (upwards in the data-flow) with their reaching defs.
for (NodeAddr<RefNode*> RA : SA.Addr->members(*this)) {
uint16_t Kind = RA.Addr->getKind();
assert(Kind == NodeAttrs::Def || Kind == NodeAttrs::Use);
- RegisterRef RR = RA.Addr->getRegRef();
- // Do not process multiple defs of the same reference.
- if (Kind == NodeAttrs::Def && Defs.count(RR))
- continue;
+ RegisterRef RR = RA.Addr->getRegRef(*this);
+#ifndef NDEBUG
+ // Do not expect multiple defs of the same reference.
+ assert(Kind != NodeAttrs::Def || !Defs.count(RR));
Defs.insert(RR);
+#endif
- auto F = DefM.find(RR);
+ auto F = DefM.find(RR.Reg);
if (F == DefM.end())
continue;
DefStack &DS = F->second;
@@ -1584,7 +1797,7 @@ void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, NodeAddr<BlockNode*> BA) {
MachineDomTreeNode *N = MDT.getNode(BA.Addr->getCode());
for (auto I : *N) {
MachineBasicBlock *SB = I->getBlock();
- auto SBA = Func.Addr->findBlock(SB, *this);
+ NodeAddr<BlockNode*> SBA = findBlock(SB);
linkBlockRefs(DefM, SBA);
}
@@ -1596,15 +1809,27 @@ void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, NodeAddr<BlockNode*> BA) {
NodeAddr<PhiUseNode*> PUA = NA;
return PUA.Addr->getPredecessor() == BA.Id;
};
+
+ RegisterSet EHLiveIns = getLandingPadLiveIns();
MachineBasicBlock *MBB = BA.Addr->getCode();
- for (auto SB : MBB->successors()) {
- auto SBA = Func.Addr->findBlock(SB, *this);
+
+ for (MachineBasicBlock *SB : MBB->successors()) {
+ bool IsEHPad = SB->isEHPad();
+ NodeAddr<BlockNode*> SBA = findBlock(SB);
for (NodeAddr<InstrNode*> IA : SBA.Addr->members_if(IsPhi, *this)) {
+ // Do not link phi uses for landing pad live-ins.
+ if (IsEHPad) {
+ // Find what register this phi is for.
+ NodeAddr<RefNode*> RA = IA.Addr->getFirstMember(*this);
+ assert(RA.Id != 0);
+ if (EHLiveIns.count(RA.Addr->getRegRef(*this)))
+ continue;
+ }
// Go over each phi use associated with MBB, and link it.
for (auto U : IA.Addr->members_if(IsUseForBA, *this)) {
NodeAddr<PhiUseNode*> PUA = U;
- RegisterRef RR = PUA.Addr->getRegRef();
- linkRefUp<UseNode*>(IA, PUA, DefM[RR]);
+ RegisterRef RR = PUA.Addr->getRegRef(*this);
+ linkRefUp<UseNode*>(IA, PUA, DefM[RR.Reg]);
}
}
}
OpenPOWER on IntegriCloud