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;
}
}
- 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);
}
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
// 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)) {
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;
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.
}
// 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)
+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 (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
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;
}
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;
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;
};
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;
};
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)) {
#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>
class MachineDominanceFrontier;
class MachineDominatorTree;
class TargetInstrInfo;
- class TargetRegisterInfo;
namespace rdf {
typedef uint32_t NodeId;
+ struct DataFlowGraph;
+
struct NodeAttrs {
enum : uint16_t {
None = 0x0000, // Nothing
};
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.
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 {
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:
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(); }
NodeAllocator Memory;
// Local map: MachineBasicBlock -> NodeAddr<BlockNode*>
std::map<MachineBasicBlock*,NodeAddr<BlockNode*>> BlockNodes;
+ // Lane mask map.
+ IndexedSet<LaneBitmask> LMMap;
MachineFunction &MF;
const TargetInstrInfo &TII;
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.
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);
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);
// 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());
// 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.
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();
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)) {
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())
// 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);
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;
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();
}
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);
}