[RDF] Add initial support for lane masks in the DFG
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Thu, 22 Sep 2016 21:01:24 +0000 (21:01 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Thu, 22 Sep 2016 21:01:24 +0000 (21:01 +0000)
Use lane masks for calculating covering and aliasing of register
references.

llvm-svn: 282194

llvm/lib/Target/Hexagon/HexagonRDF.cpp
llvm/lib/Target/Hexagon/HexagonRDF.h
llvm/lib/Target/Hexagon/RDFGraph.cpp
llvm/lib/Target/Hexagon/RDFGraph.h
llvm/lib/Target/Hexagon/RDFLiveness.cpp

index 06719cd..ec4823d 100644 (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);
 }
index 9a63150..7bcdbba 100644 (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
index bea9a83..dd39dcf 100644 (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);
-
-  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
@@ -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)) {
index 876fe24..3403b64 100644 (file)
 #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;
index 3dfa768..48de9a6 100644 (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);
       }