[llvm] r282194 - [RDF] Add initial support for lane masks in the DFG
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 22 14:01:24 PDT 2016
Author: kparzysz
Date: Thu Sep 22 16:01:24 2016
New Revision: 282194
URL: http://llvm.org/viewvc/llvm-project?rev=282194&view=rev
Log:
[RDF] Add initial support for lane masks in the DFG
Use lane masks for calculating covering and aliasing of register
references.
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonRDF.cpp
llvm/trunk/lib/Target/Hexagon/HexagonRDF.h
llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp
llvm/trunk/lib/Target/Hexagon/RDFGraph.h
llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp
Modified: llvm/trunk/lib/Target/Hexagon/HexagonRDF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonRDF.cpp?rev=282194&r1=282193&r2=282194&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonRDF.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonRDF.cpp Thu Sep 22 16:01:24 2016
@@ -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(Re
}
}
- 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);
}
Modified: llvm/trunk/lib/Target/Hexagon/HexagonRDF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonRDF.h?rev=282194&r1=282193&r2=282194&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonRDF.h (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonRDF.h Thu Sep 22 16:01:24 2016
@@ -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
Modified: llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp?rev=282194&r1=282193&r2=282194&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp Thu Sep 22 16:01:24 2016
@@ -580,14 +580,47 @@ NodeAddr<BlockNode*> FuncNode::getEntryB
// 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(RegisterR
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 Reg
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> RegisterAliasIn
}
// 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(RegisterRe
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<B
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(BlockRefsM
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(BlockRefsM
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<I
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)) {
Modified: llvm/trunk/lib/Target/Hexagon/RDFGraph.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFGraph.h?rev=282194&r1=282193&r2=282194&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFGraph.h (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFGraph.h Thu Sep 22 16:01:24 2016
@@ -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;
Modified: llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp?rev=282194&r1=282193&r2=282194&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp Thu Sep 22 16:01:24 2016
@@ -109,7 +109,7 @@ NodeList Liveness::getAllReachingDefs(Re
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(Re
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(Re
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(Re
// 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(Regi
// 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(Regi
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(Regi
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(NodeAdd
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(MachineBasicBloc
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(MachineBasicBloc
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);
}
More information about the llvm-commits
mailing list