enhance the EmitNode/MorphNodeTo operands to take a bit that
[oota-llvm.git] / utils / TableGen / DAGISelMatcher.cpp
index 0b0a1be0d62bc4477fb2e19b08419fa8ec749063..f1bfec0fc3ee5ba2d637e2cd869cf250b879ddbb 100644 (file)
 #include "CodeGenTarget.h"
 #include "Record.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
 using namespace llvm;
 
-void MatcherNode::dump() const {
-  print(errs());
+void Matcher::dump() const {
+  print(errs(), 0);
 }
 
-void MatcherNode::printNext(raw_ostream &OS, unsigned indent) const {
+void Matcher::print(raw_ostream &OS, unsigned indent) const {
+  printImpl(OS, indent);
   if (Next)
     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];
+}
 
-void PushMatcherNode::print(raw_ostream &OS, unsigned indent) const {
-  OS.indent(indent) << "Push\n";
-  printNext(OS, indent+2);
-  Failure->print(OS, indent);
+
+// printImpl methods.
+
+void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+  OS.indent(indent) << "Scope\n";
+  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 RecordMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "Record\n";
-  printNext(OS, indent);
 }
 
-void RecordChildMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "RecordChild: " << ChildNo << '\n';
-  printNext(OS, indent);
 }
 
-void RecordMemRefMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "RecordMemRef\n";
-  printNext(OS, indent);
 }
 
-void CaptureFlagInputMatcherNode::print(raw_ostream &OS, unsigned indent) const{
+void CaptureFlagInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
   OS.indent(indent) << "CaptureFlagInput\n";
-  printNext(OS, indent);
 }
 
-void MoveChildMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "MoveChild " << ChildNo << '\n';
-  printNext(OS, indent);
 }
 
-void MoveParentMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "MoveParent\n";
-  printNext(OS, indent);
 }
 
-void CheckSameMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
-  printNext(OS, indent);
 }
 
-void CheckPatternPredicateMatcherNode::
-print(raw_ostream &OS, unsigned indent) const {
+void CheckPatternPredicateMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
-  printNext(OS, indent);
 }
 
-void CheckPredicateMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckPredicate " << PredName << '\n';
-  printNext(OS, indent);
 }
 
-void CheckOpcodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
-  OS.indent(indent) << "CheckOpcode " << OpcodeName << '\n';
-  printNext(OS, indent);
+void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+  OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';
 }
 
-void CheckMultiOpcodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckMultiOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
   OS.indent(indent) << "CheckMultiOpcode <todo args>\n";
-  printNext(OS, indent);
 }
 
-void CheckTypeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckType " << getEnumName(Type) << '\n';
-  printNext(OS, indent);
 }
 
-void CheckChildTypeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckChildType " << ChildNo << " "
     << getEnumName(Type) << '\n';
-  printNext(OS, indent);
 }
 
 
-void CheckIntegerMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckInteger " << Value << '\n';
-  printNext(OS, indent);
 }
 
-void CheckCondCodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
-  printNext(OS, indent);
 }
 
-void CheckValueTypeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
-  printNext(OS, indent);
 }
 
-void CheckComplexPatMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';
-  printNext(OS, indent);
 }
 
-void CheckAndImmMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckAndImm " << Value << '\n';
-  printNext(OS, indent);
 }
 
-void CheckOrImmMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CheckOrImm " << Value << '\n';
-  printNext(OS, indent);
 }
 
-void CheckFoldableChainNodeMatcherNode::print(raw_ostream &OS,
+void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
                                               unsigned indent) const {
   OS.indent(indent) << "CheckFoldableChainNode\n";
-  printNext(OS, indent);
 }
 
-void CheckChainCompatibleMatcherNode::print(raw_ostream &OS,
+void CheckChainCompatibleMatcher::printImpl(raw_ostream &OS,
                                               unsigned indent) const {
   OS.indent(indent) << "CheckChainCompatible " << PreviousOp << "\n";
-  printNext(OS, indent);
 }
 
-void EmitIntegerMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n';
-  printNext(OS, indent);
 }
 
-void EmitStringIntegerMatcherNode::
-print(raw_ostream &OS, unsigned indent) const {
+void EmitStringIntegerMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n';
-  printNext(OS, indent);
 }
 
-void EmitRegisterMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitRegister ";
   if (Reg)
     OS << Reg->getName();
   else
     OS << "zero_reg";
   OS << " VT=" << VT << '\n';
-  printNext(OS, indent);
 }
 
-void EmitConvertToTargetMatcherNode::
-print(raw_ostream &OS, unsigned indent) const {
+void EmitConvertToTargetMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';
-  printNext(OS, indent);
 }
 
-void EmitMergeInputChainsMatcherNode::
-print(raw_ostream &OS, unsigned indent) const {
+void EmitMergeInputChainsMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";
-  printNext(OS, indent);
 }
 
-void EmitCopyToRegMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitCopyToReg <todo: args>\n";
-  printNext(OS, indent);
 }
 
-void EmitNodeXFormMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()
      << " Slot=" << Slot << '\n';
-  printNext(OS, indent);
 }
 
 
-void EmitNodeMatcherNode::print(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]);
@@ -194,18 +185,152 @@ void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
   for (unsigned i = 0, e = Operands.size(); i != e; ++i)
     OS << Operands[i] << ' ';
   OS << ")\n";
-  printNext(OS, indent);
 }
 
-void MarkFlagResultsMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void MarkFlagResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "MarkFlagResults <todo: args>\n";
-  printNext(OS, indent);
 }
 
-void CompleteMatchMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "CompleteMatch <todo args>\n";
   OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
   OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
-  printNext(OS, indent);
 }
 
+// getHashImpl Implementation.
+
+unsigned CheckPatternPredicateMatcher::getHashImpl() const {
+  return HashString(Predicate);
+}
+
+unsigned CheckPredicateMatcher::getHashImpl() const {
+  return HashString(PredName);
+}
+
+unsigned CheckOpcodeMatcher::getHashImpl() const {
+  return HashString(Opcode.getEnumName());
+}
+
+unsigned CheckMultiOpcodeMatcher::getHashImpl() const {
+  unsigned Result = 0;
+  for (unsigned i = 0, e = Opcodes.size(); i != e; ++i)
+    Result |= HashString(Opcodes[i]->getEnumName());
+  return Result;
+}
+
+unsigned CheckCondCodeMatcher::getHashImpl() const {
+  return HashString(CondCodeName);
+}
+
+unsigned CheckValueTypeMatcher::getHashImpl() const {
+  return HashString(TypeName);
+}
+
+unsigned EmitStringIntegerMatcher::getHashImpl() const {
+  return HashString(Val) ^ VT;
+}
+
+template<typename It>
+static unsigned HashUnsigneds(It I, It E) {
+  unsigned Result = 0;
+  for (; I != E; ++I)
+    Result = (Result<<3) ^ *I;
+  return Result;
+}
+
+unsigned EmitMergeInputChainsMatcher::getHashImpl() const {
+  return HashUnsigneds(ChainNodes.begin(), ChainNodes.end());
+}
+
+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->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag &&
+         M->HasMemRefs == HasMemRefs &&
+         M->NumFixedArityOperands == NumFixedArityOperands;
+}
+
+unsigned EmitNodeMatcherCommon::getHashImpl() const {
+  return (HashString(OpcodeName) << 4) | Operands.size();
+}
+
+
+unsigned MarkFlagResultsMatcher::getHashImpl() const {
+  return HashUnsigneds(FlagResultNodes.begin(), FlagResultNodes.end());
+}
+
+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;
+}