enhance the EmitNode/MorphNodeTo operands to take a bit that
[oota-llvm.git] / utils / TableGen / DAGISelMatcher.cpp
index 561d6127e8e164839bf8a23c5e4b10baad01c694..f1bfec0fc3ee5ba2d637e2cd869cf250b879ddbb 100644 (file)
@@ -25,6 +25,10 @@ void Matcher::print(raw_ostream &OS, unsigned indent) const {
     return Next->print(OS, indent);
 }
 
+void Matcher::printOne(raw_ostream &OS) const {
+  printImpl(OS, 0);
+}
+
 ScopeMatcher::~ScopeMatcher() {
   for (unsigned i = 0, e = Children.size(); i != e; ++i)
     delete Children[i];
@@ -35,8 +39,12 @@ ScopeMatcher::~ScopeMatcher() {
 
 void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "Scope\n";
-  for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
-    getChild(i)->print(OS, indent+2);
+  for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+    if (getChild(i) == 0)
+      OS.indent(indent+1) << "NULL POINTER\n";
+    else
+      getChild(i)->print(OS, indent+2);
+  }
 }
 
 void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -77,7 +85,7 @@ void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
 }
 
 void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
-  OS.indent(indent) << "CheckOpcode " << OpcodeName << '\n';
+  OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';
 }
 
 void CheckMultiOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
@@ -166,8 +174,10 @@ void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
 }
 
 
-void EmitNodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
-  OS.indent(indent) << "EmitNode: " << OpcodeName << ": <todo flags> ";
+void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
+  OS.indent(indent);
+  OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")
+     << OpcodeName << ": <todo flags> ";
 
   for (unsigned i = 0, e = VTs.size(); i != e; ++i)
     OS << ' ' << getEnumName(VTs[i]);
@@ -198,13 +208,13 @@ unsigned CheckPredicateMatcher::getHashImpl() const {
 }
 
 unsigned CheckOpcodeMatcher::getHashImpl() const {
-  return HashString(OpcodeName);
+  return HashString(Opcode.getEnumName());
 }
 
 unsigned CheckMultiOpcodeMatcher::getHashImpl() const {
   unsigned Result = 0;
-  for (unsigned i = 0, e = OpcodeNames.size(); i != e; ++i)
-    Result |= HashString(OpcodeNames[i]);
+  for (unsigned i = 0, e = Opcodes.size(); i != e; ++i)
+    Result |= HashString(Opcodes[i]->getEnumName());
   return Result;
 }
 
@@ -232,15 +242,16 @@ unsigned EmitMergeInputChainsMatcher::getHashImpl() const {
   return HashUnsigneds(ChainNodes.begin(), ChainNodes.end());
 }
 
-bool EmitNodeMatcher::isEqualImpl(const Matcher *m) const {
-  const EmitNodeMatcher *M = cast<EmitNodeMatcher>(m);
+bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
+  const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
   return M->OpcodeName == OpcodeName && M->VTs == VTs &&
          M->Operands == Operands && M->HasChain == HasChain &&
-         M->HasFlag == HasFlag && M->HasMemRefs == HasMemRefs &&
+         M->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag &&
+         M->HasMemRefs == HasMemRefs &&
          M->NumFixedArityOperands == NumFixedArityOperands;
 }
 
-unsigned EmitNodeMatcher::getHashImpl() const {
+unsigned EmitNodeMatcherCommon::getHashImpl() const {
   return (HashString(OpcodeName) << 4) | Operands.size();
 }
 
@@ -253,3 +264,73 @@ unsigned CompleteMatchMatcher::getHashImpl() const {
   return HashUnsigneds(Results.begin(), Results.end()) ^ 
           ((unsigned)(intptr_t)&Pattern << 8);
 }
+
+// isContradictoryImpl Implementations.
+
+static bool TypesAreContradictory(MVT::SimpleValueType T1,
+                                  MVT::SimpleValueType T2) {
+  // If the two types are the same, then they are the same, so they don't
+  // contradict.
+  if (T1 == T2) return false;
+  
+  // If either type is about iPtr, then they don't conflict unless the other
+  // one is not a scalar integer type.
+  if (T1 == MVT::iPTR)
+    return !MVT(T2).isInteger() || MVT(T2).isVector();
+  
+  if (T2 == MVT::iPTR)
+    return !MVT(T1).isInteger() || MVT(T1).isVector();
+  
+  // Otherwise, they are two different non-iPTR types, they conflict.
+  return true;
+}
+
+bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {
+  if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {
+    // One node can't have two different opcodes!
+    return &COM->getOpcode() != &getOpcode();
+  }
+  
+  // TODO: CheckMultiOpcodeMatcher?
+  
+  // If the node has a known type, and if the type we're checking for is
+  // different, then we know they contradict.  For example, a check for
+  // ISD::STORE will never be true at the same time a check for Type i32 is.
+  if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {
+    // FIXME: What result is this referring to?
+    unsigned NodeType;
+    if (getOpcode().getNumResults() == 0)
+      NodeType = MVT::isVoid;
+    else
+      NodeType = getOpcode().getKnownType();
+    if (NodeType != EEVT::isUnknown)
+      return TypesAreContradictory((MVT::SimpleValueType)NodeType,
+                                   CT->getType());
+  }
+  
+  return false;
+}
+
+bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+  if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))
+    return TypesAreContradictory(getType(), CT->getType());
+  return false;
+}
+
+bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+  if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {
+    // If the two checks are about different nodes, we don't know if they
+    // conflict!
+    if (CC->getChildNo() != getChildNo())
+      return false;
+    
+    return TypesAreContradictory(getType(), CC->getType());
+  }
+  return false;
+}
+  
+bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
+  if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))
+    return CIM->getValue() != getValue();
+  return false;
+}