[RDF] Add initial support for lane masks in the DFG

Use lane masks for calculating covering and aliasing of register
references.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282194 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Krzysztof Parzyszek 2016-09-22 21:01:24 +00:00
parent a9c167e82e
commit 319d69e0f2
5 changed files with 162 additions and 61 deletions

View File

@ -16,7 +16,8 @@
using namespace llvm;
using namespace rdf;
bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const {
bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB,
const DataFlowGraph &DFG) const {
if (RA == RB)
return true;
@ -31,30 +32,33 @@ bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const {
}
}
return RegisterAliasInfo::covers(RA, RB);
return RegisterAliasInfo::covers(RA, RB, DFG);
}
bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR)
const {
bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR,
const DataFlowGraph &DFG) const {
if (RRs.count(RR))
return true;
if (!TargetRegisterInfo::isPhysicalRegister(RR.Reg)) {
assert(TargetRegisterInfo::isVirtualRegister(RR.Reg));
// Check if both covering subregisters are present.
// The exact reference RR is not in the set.
if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) {
// Check if the there are references in RRs of the same register,
// with both covering subregisters.
bool HasLo = RRs.count({RR.Reg, Hexagon::subreg_loreg});
bool HasHi = RRs.count({RR.Reg, Hexagon::subreg_hireg});
if (HasLo && HasHi)
return true;
}
if (RR.Sub == 0) {
// Check if both covering subregisters are present.
if (TargetRegisterInfo::isPhysicalRegister(RR.Reg)) {
// Check if both covering subregisters are present with full
// lane masks.
unsigned Lo = TRI.getSubReg(RR.Reg, Hexagon::subreg_loreg);
unsigned Hi = TRI.getSubReg(RR.Reg, Hexagon::subreg_hireg);
if (RRs.count({Lo, 0}) && RRs.count({Hi, 0}))
return true;
}
return RegisterAliasInfo::covers(RRs, RR);
return RegisterAliasInfo::covers(RRs, RR, DFG);
}

View File

@ -18,8 +18,10 @@ namespace rdf {
struct HexagonRegisterAliasInfo : public RegisterAliasInfo {
HexagonRegisterAliasInfo(const TargetRegisterInfo &TRI)
: RegisterAliasInfo(TRI) {}
bool covers(RegisterRef RA, RegisterRef RR) const override;
bool covers(const RegisterSet &RRs, RegisterRef RR) const override;
bool covers(RegisterRef RA, RegisterRef RR,
const DataFlowGraph &DFG) const override;
bool covers(const RegisterSet &RRs, RegisterRef RR,
const DataFlowGraph &DFG) const override;
};
} // namespace rdf
} // namespace llvm

View File

@ -580,14 +580,47 @@ NodeAddr<BlockNode*> FuncNode::getEntryBlock(const DataFlowGraph &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.
LaneBitmask RegisterAliasInfo::getLaneMask(RegisterRef RR,
const DataFlowGraph &DFG) const {
assert(TargetRegisterInfo::isPhysicalRegister(RR.Reg));
const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(RR.Reg);
return (RR.Sub != 0) ? DFG.getLaneMaskForIndex(RR.Sub) : RC->LaneMask;
}
RegisterAliasInfo::CommonRegister::CommonRegister(
unsigned RegA, LaneBitmask LA, unsigned RegB, LaneBitmask LB,
const TargetRegisterInfo &TRI) {
if (RegA == RegB) {
SuperReg = RegA;
MaskA = LA;
MaskB = LB;
return;
}
// Find a common super-register.
SuperReg = 0;
for (MCSuperRegIterator SA(RegA, &TRI, true); SA.isValid(); ++SA) {
if (!TRI.isSubRegisterEq(*SA, RegB))
continue;
SuperReg = *SA;
break;
}
if (SuperReg == 0)
return;
if (unsigned SubA = TRI.getSubRegIndex(SuperReg, RegA))
LA = TRI.composeSubRegIndexLaneMask(SubA, LA);
if (unsigned SubB = TRI.getSubRegIndex(SuperReg, RegB))
LB = TRI.composeSubRegIndexLaneMask(SubB, LB);
MaskA = LA;
MaskB = LB;
}
// Determine whether RA covers RB.
bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const {
bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB,
const DataFlowGraph &DFG) const {
if (RA == RB)
return true;
if (TargetRegisterInfo::isVirtualRegister(RA.Reg)) {
@ -601,13 +634,17 @@ bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const {
assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg) &&
TargetRegisterInfo::isPhysicalRegister(RB.Reg));
uint32_t A = RA.Sub != 0 ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg;
uint32_t B = RB.Sub != 0 ? TRI.getSubReg(RB.Reg, RB.Sub) : RB.Reg;
return TRI.isSubRegister(A, B);
CommonRegister CR(RA.Reg, getLaneMask(RA, DFG),
RB.Reg, getLaneMask(RB, DFG), TRI);
if (CR.SuperReg == 0)
return false;
return (CR.MaskA & CR.MaskB) == CR.MaskB;
}
// Determine whether RR is covered by the set of references RRs.
bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) const {
bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR,
const DataFlowGraph &DFG) const {
if (RRs.count(RR))
return true;
@ -630,7 +667,7 @@ bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) const {
return false;
}
// Get the list of references aliased to RR.
// Get the list of references aliased to RR. Lane masks are ignored.
std::vector<RegisterRef> RegisterAliasInfo::getAliasSet(RegisterRef RR) const {
// Do not include RR in the alias set. For virtual registers return an
// empty set.
@ -648,16 +685,17 @@ std::vector<RegisterRef> RegisterAliasInfo::getAliasSet(RegisterRef RR) const {
}
// 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);
bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB,
const DataFlowGraph &DFG) const {
bool IsVirtA = TargetRegisterInfo::isVirtualRegister(RA.Reg);
bool IsVirtB = TargetRegisterInfo::isVirtualRegister(RB.Reg);
bool IsPhysA = TargetRegisterInfo::isPhysicalRegister(RA.Reg);
bool IsPhysB = TargetRegisterInfo::isPhysicalRegister(RB.Reg);
if (VirtA != VirtB)
if (IsVirtA != IsVirtB)
return false;
if (VirtA) {
if (IsVirtA) {
if (RA.Reg != RB.Reg)
return false;
// RA and RB refer to the same register. If any of them refer to the
@ -675,14 +713,14 @@ bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB) const {
return false;
}
assert(PhysA && PhysB);
(void)PhysA, (void)PhysB;
uint32_t A = RA.Sub ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg;
uint32_t 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;
assert(IsPhysA && IsPhysB);
(void)IsPhysA, (void)IsPhysB;
CommonRegister CR(RA.Reg, getLaneMask(RA, DFG),
RB.Reg, getLaneMask(RB, DFG), TRI);
if (CR.SuperReg == 0)
return false;
return (CR.MaskA & CR.MaskB) != 0;
}
@ -1213,7 +1251,7 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
if (!UseOp.isReg() || !UseOp.isUse() || UseOp.isUndef())
continue;
RegisterRef UR = { UseOp.getReg(), UseOp.getSubReg() };
if (RAI.alias(DR, UR))
if (RAI.alias(DR, UR, *this))
return false;
}
return true;
@ -1398,7 +1436,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM,
auto MaxCoverIn = [this] (RegisterRef RR, RegisterSet &RRs) -> RegisterRef {
for (auto I : RRs)
if (I != RR && RAI.covers(I, RR))
if (I != RR && RAI.covers(I, RR, *this))
RR = I;
return RR;
};
@ -1425,7 +1463,7 @@ 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]))
if (RAI.alias(RR, MaxRefs[I], *this))
return true;
return false;
};
@ -1544,9 +1582,9 @@ void DataFlowGraph::linkRefUp(NodeAddr<InstrNode*> IA, NodeAddr<T> TA,
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);
return RAI.alias(QR, RR, *this);
};
bool PrecUp = RAI.covers(QR, RR);
bool PrecUp = RAI.covers(QR, RR, *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 (any_of(Defs, AliasQR)) {

View File

@ -221,6 +221,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Timer.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <functional>
#include <map>
@ -236,11 +237,12 @@ namespace llvm {
class MachineDominanceFrontier;
class MachineDominatorTree;
class TargetInstrInfo;
class TargetRegisterInfo;
namespace rdf {
typedef uint32_t NodeId;
struct DataFlowGraph;
struct NodeAttrs {
enum : uint16_t {
None = 0x0000, // Nothing
@ -384,6 +386,15 @@ namespace rdf {
};
struct RegisterRef {
// For virtual registers, Reg and Sub have the usual meanings.
//
// Physical registers are assumed not to have any subregisters, and for
// them, Sub is the key of the LaneBitmask in the lane mask map in DFG.
// The case of Sub = 0 is treated as 'all lanes', i.e. lane mask of ~0.
// Use an key/map to access lane masks, since we only have uint32_t
// for it, and the LaneBitmask type can grow in the future.
//
// The case when Reg = 0 and Sub = 0 is reserved to mean "no register".
uint32_t Reg, Sub;
// No non-trivial constructors, since this will be a member of a union.
@ -407,11 +418,25 @@ namespace rdf {
virtual ~RegisterAliasInfo() {}
virtual std::vector<RegisterRef> getAliasSet(RegisterRef RR) const;
virtual bool alias(RegisterRef RA, RegisterRef RB) const;
virtual bool covers(RegisterRef RA, RegisterRef RB) const;
virtual bool covers(const RegisterSet &RRs, RegisterRef RR) const;
virtual bool alias(RegisterRef RA, RegisterRef RB,
const DataFlowGraph &DFG) const;
virtual bool covers(RegisterRef RA, RegisterRef RB,
const DataFlowGraph &DFG) const;
virtual bool covers(const RegisterSet &RRs, RegisterRef RR,
const DataFlowGraph &DFG) const;
const TargetRegisterInfo &TRI;
protected:
LaneBitmask getLaneMask(RegisterRef RR, const DataFlowGraph &DFG) const;
struct CommonRegister {
CommonRegister(unsigned RegA, LaneBitmask LA,
unsigned RegB, LaneBitmask LB,
const TargetRegisterInfo &TRI);
unsigned SuperReg;
LaneBitmask MaskA, MaskB;
};
};
struct TargetOperandInfo {
@ -424,8 +449,31 @@ namespace rdf {
const TargetInstrInfo &TII;
};
// Template class for a map translating uint32_t into arbitrary types.
// The map will act like an indexed set: upon insertion of a new object,
// it will automatically assign a new index to it. Index of 0 is treated
// as invalid and is never allocated.
template <typename T, unsigned N = 32>
struct IndexedSet {
IndexedSet() : Map(N) {}
const T get(uint32_t Idx) const {
// Index Idx corresponds to Map[Idx-1].
assert(Idx != 0 && !Map.empty() && Idx-1 < Map.size());
return Map[Idx-1];
}
uint32_t insert(T Val) {
// Linear search.
auto F = find(Map, Val);
if (F != Map.end())
return *F;
Map.push_back(Val);
return Map.size(); // Return actual_index + 1.
}
private:
std::vector<T> Map;
};
struct DataFlowGraph;
struct NodeBase {
public:
@ -648,6 +696,13 @@ namespace rdf {
return RAI;
}
LaneBitmask getLaneMaskForIndex(uint32_t K) const {
return LMMap.get(K);
}
uint32_t getIndexForLaneMask(LaneBitmask LM) {
return LMMap.insert(LM);
}
struct DefStack {
DefStack() = default;
bool empty() const { return Stack.empty() || top() == bottom(); }
@ -820,6 +875,8 @@ namespace rdf {
NodeAllocator Memory;
// Local map: MachineBasicBlock -> NodeAddr<BlockNode*>
std::map<MachineBasicBlock*,NodeAddr<BlockNode*>> BlockNodes;
// Lane mask map.
IndexedSet<LaneBitmask> LMMap;
MachineFunction &MF;
const TargetInstrInfo &TII;

View File

@ -109,7 +109,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
continue;
// Stop at the covering/overwriting def of the initial register reference.
RegisterRef RR = TA.Addr->getRegRef();
if (!DFG.IsPreservingDef(TA) && RAI.covers(RR, RefRR))
if (!DFG.IsPreservingDef(TA) && RAI.covers(RR, RefRR, DFG))
continue;
// Get the next level of reaching defs. This will include multiple
// reaching defs for shadows.
@ -124,7 +124,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
for (auto 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 && !RAI.alias(RefRR, TA.Addr->getRegRef(), DFG))
continue;
Defs.insert(TA.Id);
Owners.insert(TA.Addr->getOwner(DFG).Id);
@ -194,7 +194,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
Defs.count(TA.Id);
};
for (auto T : Tmp) {
if (!FullChain && RAI.covers(RRs, RefRR))
if (!FullChain && RAI.covers(RRs, RefRR, DFG))
break;
auto TA = DFG.addr<InstrNode*>(T);
bool IsPhi = DFG.IsCode<NodeAttrs::Phi>(TA);
@ -209,7 +209,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 || !RAI.covers(RRs, QR, DFG))
Ds.push_back(DA);
}
RDefs.insert(RDefs.end(), Ds.begin(), Ds.end());
@ -281,7 +281,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
// If the original register is already covered by all the intervening
// defs, no more uses can be reached.
if (RAI.covers(DefRRs, RefRR))
if (RAI.covers(DefRRs, RefRR, DFG))
return Uses;
// Add all directly reached uses.
@ -290,7 +290,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
auto UA = DFG.addr<UseNode*>(U);
if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) {
auto UR = UA.Addr->getRegRef();
if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR))
if (RAI.alias(RefRR, UR, DFG) && !RAI.covers(DefRRs, UR, DFG))
Uses.insert(U);
}
U = UA.Addr->getSibling();
@ -303,7 +303,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
auto DR = DA.Addr->getRegRef();
// 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 (RAI.covers(DefRRs, DR, DFG) || !RAI.alias(RefRR, DR, DFG))
continue;
NodeSet T;
if (DFG.IsPreservingDef(DA)) {
@ -514,7 +514,7 @@ void Liveness::computePhiInfo() {
RegisterRef R = T.first;
if (!isRestrictedToRef(PA, UA, R))
R = getRestrictedRegRef(UA);
if (!RAI.covers(MidDefs, R))
if (!RAI.covers(MidDefs, R, DFG))
UpReached.insert(R);
}
if (UpReached.empty())
@ -635,7 +635,7 @@ void Liveness::computeLiveIns() {
// 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))
if (!RAI.alias(R.first, RR, DFG))
continue;
for (auto D : getAllReachingDefs(RR, UA))
LOX[RR].insert(D.Id);
@ -768,7 +768,7 @@ bool Liveness::isRestrictedToRef(NodeAddr<InstrNode*> IA, NodeAddr<RefNode*> RA,
NodeId RD = TA.Addr->getReachingDef();
if (RD == 0)
continue;
if (RAI.alias(RR, DFG.addr<DefNode*>(RD).Addr->getRegRef()))
if (RAI.alias(RR, DFG.addr<DefNode*>(RD).Addr->getRegRef(), DFG))
return false;
}
return true;
@ -880,13 +880,13 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
else {
bool IsPreserving = DFG.IsPreservingDef(DA);
if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) {
bool Covering = RAI.covers(DDR, I.first);
bool Covering = RAI.covers(DDR, I.first, DFG);
NodeId U = DA.Addr->getReachedUse();
while (U && Covering) {
auto DUA = DFG.addr<UseNode*>(U);
if (!(DUA.Addr->getFlags() & NodeAttrs::Undef)) {
RegisterRef Q = DUA.Addr->getRegRef();
Covering = RAI.covers(DA.Addr->getRegRef(), Q);
Covering = RAI.covers(DA.Addr->getRegRef(), Q, DFG);
}
U = DUA.Addr->getSibling();
}
@ -909,7 +909,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
RRs.insert(TA.Addr->getRegRef());
if (BA.Addr->getCode() == B)
continue;
if (RAI.covers(RRs, DRR))
if (RAI.covers(RRs, DRR, DFG))
break;
Defs.insert(TA.Id);
}