[llvm-commits] [llvm] r125245 - in /llvm/trunk: test/MC/ARM/simple-fp-encoding.s utils/TableGen/AsmMatcherEmitter.cpp

Jim Grosbach grosbach at apple.com
Wed Feb 9 16:08:28 PST 2011


Author: grosbach
Date: Wed Feb  9 18:08:28 2011
New Revision: 125245

URL: http://llvm.org/viewvc/llvm-project?rev=125245&view=rev
Log:
Do AsmMatcher operand classification per-opcode.

When matching operands for a candidate opcode match in the auto-generated
AsmMatcher, check each operand against the expected operand match class.
Previously, operands were classified independently of the opcode being
handled, which led to difficulties when operand match classes were
more complicated than simple subclass relationships.


Modified:
    llvm/trunk/test/MC/ARM/simple-fp-encoding.s
    llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp

Modified: llvm/trunk/test/MC/ARM/simple-fp-encoding.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/simple-fp-encoding.s?rev=125245&r1=125244&r2=125245&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/simple-fp-encoding.s (original)
+++ llvm/trunk/test/MC/ARM/simple-fp-encoding.s Wed Feb  9 18:08:28 2011
@@ -1,5 +1,4 @@
 @ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7-apple-darwin -show-encoding < %s | FileCheck %s
-@ XFAIL: *
 
 @ CHECK: vadd.f64 d16, d17, d16      @ encoding: [0xa0,0x0b,0x71,0xee]
         vadd.f64        d16, d17, d16

Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=125245&r1=125244&r2=125245&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Wed Feb  9 18:08:28 2011
@@ -1621,37 +1621,35 @@
   OS << "}\n\n";
 }
 
-/// EmitClassifyOperand - Emit the function to classify an operand.
-static void EmitClassifyOperand(AsmMatcherInfo &Info,
-                                raw_ostream &OS) {
-  OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
-     << "  " << Info.Target.getName() << "Operand &Operand = *("
+/// EmitValidateOperandClass - Emit the function to validate an operand class.
+static void EmitValidateOperandClass(AsmMatcherInfo &Info,
+                                     raw_ostream &OS) {
+  OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, "
+     << "MatchClassKind Kind) {\n";
+  OS << "  " << Info.Target.getName() << "Operand &Operand = *("
      << Info.Target.getName() << "Operand*)GOp;\n";
 
-  // Classify tokens.
+  // Check for Token operands first.
   OS << "  if (Operand.isToken())\n";
-  OS << "    return MatchTokenString(Operand.getToken());\n\n";
+  OS << "    return MatchTokenString(Operand.getToken()) == Kind;\n\n";
 
-  // Classify registers.
-  //
-  // FIXME: Don't hardcode isReg, getReg.
+  // Check for register operands, including sub-classes.
   OS << "  if (Operand.isReg()) {\n";
+  OS << "    MatchClassKind OpKind;\n";
   OS << "    switch (Operand.getReg()) {\n";
-  OS << "    default: return InvalidMatchClass;\n";
+  OS << "    default: OpKind = InvalidMatchClass; break;\n";
   for (std::map<Record*, ClassInfo*>::iterator
          it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
        it != ie; ++it)
     OS << "    case " << Info.Target.getName() << "::"
-       << it->first->getName() << ": return " << it->second->Name << ";\n";
+       << it->first->getName() << ": OpKind = " << it->second->Name
+       << "; break;\n";
   OS << "    }\n";
+  OS << "    return IsSubclass(OpKind, Kind);\n";
   OS << "  }\n\n";
 
-  // Classify user defined operands.  To do so, we need to perform a topological
-  // sort of the superclass relationship graph so that we always match the
-  // narrowest type first.
-
-  // Collect the incoming edge counts for each class.
-  std::map<ClassInfo*, unsigned> IncomingEdges;
+  // Check the user classes. We don't care what order since we're only
+  // actually matching against one of them.
   for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
          ie = Info.Classes.end(); it != ie; ++it) {
     ClassInfo &CI = **it;
@@ -1659,58 +1657,14 @@
     if (!CI.isUserClass())
       continue;
 
-    for (std::vector<ClassInfo*>::iterator SI = CI.SuperClasses.begin(),
-         SE = CI.SuperClasses.end(); SI != SE; ++SI)
-      ++IncomingEdges[*SI];
-  }
-
-  // Initialize a worklist of classes with no incoming edges.
-  std::vector<ClassInfo*> LeafClasses;
-  for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
-         ie = Info.Classes.end(); it != ie; ++it) {
-    if (!IncomingEdges[*it])
-      LeafClasses.push_back(*it);
-  }
-
-  // Iteratively pop the list, process that class, and update the incoming
-  // edge counts for its super classes.  When a superclass reaches zero
-  // incoming edges, push it onto the worklist for processing.
-  while (!LeafClasses.empty()) {
-    ClassInfo &CI = *LeafClasses.back();
-    LeafClasses.pop_back();
-
-    if (!CI.isUserClass())
-      continue;
-
-    OS << "  // '" << CI.ClassName << "' class";
-    if (!CI.SuperClasses.empty()) {
-      OS << ", subclass of ";
-      for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) {
-        if (i) OS << ", ";
-        OS << "'" << CI.SuperClasses[i]->ClassName << "'";
-        assert(CI < *CI.SuperClasses[i] && "Invalid class relation!");
-
-        --IncomingEdges[CI.SuperClasses[i]];
-        if (!IncomingEdges[CI.SuperClasses[i]])
-          LeafClasses.push_back(CI.SuperClasses[i]);
-      }
-    }
-    OS << "\n";
-
-    OS << "  if (Operand." << CI.PredicateMethod << "()) {\n";
-
-    // Validate subclass relationships.
-    if (!CI.SuperClasses.empty()) {
-      for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i)
-        OS << "    assert(Operand." << CI.SuperClasses[i]->PredicateMethod
-           << "() && \"Invalid class relationship!\");\n";
-    }
-
-    OS << "    return " << CI.Name << ";\n";
+    OS << "  // '" << CI.ClassName << "' class\n";
+    OS << "  if (Kind == " << CI.Name
+       << " && Operand." << CI.PredicateMethod << "()) {\n";
+    OS << "    return true;\n";
     OS << "  }\n\n";
   }
 
-  OS << "  return InvalidMatchClass;\n";
+  OS << "  return false;\n";
   OS << "}\n\n";
 }
 
@@ -2215,12 +2169,12 @@
   // Emit the routine to match token strings to their match class.
   EmitMatchTokenString(Target, Info.Classes, OS);
 
-  // Emit the routine to classify an operand.
-  EmitClassifyOperand(Info, OS);
-
   // Emit the subclass predicate routine.
   EmitIsSubclass(Target, Info.Classes, OS);
 
+  // Emit the routine to validate an operand against a match class.
+  EmitValidateOperandClass(Info, OS);
+
   // Emit the available features compute function.
   EmitComputeAvailableFeatures(Info, OS);
 
@@ -2335,23 +2289,6 @@
   OS << "    return Match_InvalidOperand;\n";
   OS << "  }\n\n";
 
-  OS << "  // Compute the class list for this operand vector.\n";
-  OS << "  MatchClassKind Classes[" << MaxNumOperands << "];\n";
-  OS << "  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {\n";
-  OS << "    Classes[i-1] = ClassifyOperand(Operands[i]);\n\n";
-
-  OS << "    // Check for invalid operands before matching.\n";
-  OS << "    if (Classes[i-1] == InvalidMatchClass) {\n";
-  OS << "      ErrorInfo = i;\n";
-  OS << "      return Match_InvalidOperand;\n";
-  OS << "    }\n";
-  OS << "  }\n\n";
-
-  OS << "  // Mark unused classes.\n";
-  OS << "  for (unsigned i = Operands.size()-1, e = " << MaxNumOperands << "; "
-     << "i != e; ++i)\n";
-  OS << "    Classes[i] = InvalidMatchClass;\n\n";
-
   OS << "  // Some state to try to produce better error messages.\n";
   OS << "  bool HadMatchOtherThanFeatures = false;\n\n";
   OS << "  // Set ErrorInfo to the operand that mismatches if it is \n";
@@ -2378,7 +2315,11 @@
   // Emit check that the subclasses match.
   OS << "    bool OperandsValid = true;\n";
   OS << "    for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
-  OS << "      if (IsSubclass(Classes[i], it->Classes[i]))\n";
+  OS << "      if (i + 1 >= Operands.size()) {\n";
+  OS << "        OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
+  OS << "        break;";
+  OS << "      }\n";
+  OS << "      if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n";
   OS << "        continue;\n";
   OS << "      // If this operand is broken for all of the instances of this\n";
   OS << "      // mnemonic, keep track of it so we can report loc info.\n";





More information about the llvm-commits mailing list