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

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

llvm-svn: 282194
diff --git a/llvm/lib/Target/Hexagon/RDFGraph.cpp b/llvm/lib/Target/Hexagon/RDFGraph.cpp
index bea9a83..dd39dcf 100644
--- a/llvm/lib/Target/Hexagon/RDFGraph.cpp
+++ b/llvm/lib/Target/Hexagon/RDFGraph.cpp
@@ -580,14 +580,47 @@
 
 // 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 @@
 
   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 @@
   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 @@
 }
 
 // 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 @@
     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 @@
       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 @@
 
   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 @@
   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 @@
   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)) {