[SelectionDAG] Add a SDTCisSameSizeAs type constraint that can be used to ensure...
authorCraig Topper <craig.topper@gmail.com>
Thu, 26 Nov 2015 07:02:18 +0000 (07:02 +0000)
committerCraig Topper <craig.topper@gmail.com>
Thu, 26 Nov 2015 07:02:18 +0000 (07:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254138 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetSelectionDAG.td
utils/TableGen/CodeGenDAGPatterns.cpp
utils/TableGen/CodeGenDAGPatterns.h

index fd0e049..905b1cf 100644 (file)
@@ -80,6 +80,11 @@ class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> {
   int OtherOperandNum = OtherOp;
 }
 
+// SDTCisSameSizeAs - The two specified operands have identical size.
+class SDTCisSameSizeAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> {
+  int OtherOperandNum = OtherOp;
+}
+
 //===----------------------------------------------------------------------===//
 // Selection DAG Type Profile definitions.
 //
index 025e419..38a8653 100644 (file)
@@ -635,6 +635,60 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
   return MadeChange;
 }
 
+/// EnforceSameSize - 'this' is now constrained to be same size as VTOperand.
+bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
+                                    TreePattern &TP) {
+  if (TP.hasError())
+    return false;
+
+  bool MadeChange = false;
+
+  // If we know one of the types, it forces the other type agree.
+  if (isConcrete()) {
+    MVT IVT = getConcrete();
+    unsigned Size = IVT.getSizeInBits();
+
+    // Only keep types that have the same size as 'this'.
+    TypeSet InputSet(VTOperand);
+
+    auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
+                            [&](MVT VT) {
+                              return VT.getSizeInBits() != Size;
+                            });
+    MadeChange |= I != VTOperand.TypeVec.end();
+    VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+    if (VTOperand.TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
+      TP.error("Type inference contradiction found, forcing '" +
+               InputSet.getName() + "' to have same size as '" +
+               getName() + "'");
+      return false;
+    }
+  } else if (VTOperand.isConcrete()) {
+    MVT IVT = VTOperand.getConcrete();
+    unsigned Size = IVT.getSizeInBits();
+
+    // Only keep types that have the same size as VTOperand.
+    TypeSet InputSet(*this);
+
+    auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+                            [&](MVT VT) {
+                              return VT.getSizeInBits() != Size;
+                            });
+    MadeChange |= I != TypeVec.end();
+    TypeVec.erase(I, TypeVec.end());
+
+    if (TypeVec.empty()) {  // FIXME: Really want an SMLoc here!
+      TP.error("Type inference contradiction found, forcing '" +
+               InputSet.getName() + "' to have same size as '" +
+               VTOperand.getName() + "'");
+      return false;
+    }
+  }
+
+  return MadeChange;
+}
+
 //===----------------------------------------------------------------------===//
 // Helpers for working with extended types.
 
@@ -874,6 +928,10 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
     ConstraintType = SDTCisSameNumEltsAs;
     x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
       R->getValueAsInt("OtherOperandNum");
+  } else if (R->isSubClassOf("SDTCisSameSizeAs")) {
+    ConstraintType = SDTCisSameSizeAs;
+    x.SDTCisSameSizeAs_Info.OtherOperandNum =
+      R->getValueAsInt("OtherOperandNum");
   } else {
     PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
   }
@@ -1003,6 +1061,14 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
     return OtherNode->getExtType(OResNo).
       EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
   }
+  case SDTCisSameSizeAs: {
+    unsigned OResNo = 0;
+    TreePatternNode *OtherNode =
+      getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum,
+                    N, NodeInfo, OResNo);
+    return OtherNode->getExtType(OResNo).
+      EnforceSameSize(NodeToApply->getExtType(ResNo), TP);
+  }
   }
   llvm_unreachable("Invalid ConstraintType!");
 }
index f330e55..76c9cef 100644 (file)
@@ -148,6 +148,9 @@ namespace EEVT {
     /// be a vector with same num elements as VT.
     bool EnforceVectorSameNumElts(EEVT::TypeSet &VT, TreePattern &TP);
 
+    /// EnforceSameSize - 'this' is now constrained to be the same size as VT.
+    bool EnforceSameSize(EEVT::TypeSet &VT, TreePattern &TP);
+
     bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
     bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
 
@@ -173,7 +176,7 @@ struct SDTypeConstraint {
   enum {
     SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
     SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
-    SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs
+    SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs, SDTCisSameSizeAs
   } ConstraintType;
 
   union {   // The discriminated union.
@@ -201,6 +204,9 @@ struct SDTypeConstraint {
     struct {
       unsigned OtherOperandNum;
     } SDTCisSameNumEltsAs_Info;
+    struct {
+      unsigned OtherOperandNum;
+    } SDTCisSameSizeAs_Info;
   } x;
 
   /// ApplyTypeConstraint - Given a node in a pattern, apply this type