[llvm] r222038 - Change order of tablegen generated fast-isel instruction code to be

Bill Schmidt wschmidt at linux.vnet.ibm.com
Fri Nov 14 13:05:45 PST 2014


Author: wschmidt
Date: Fri Nov 14 15:05:45 2014
New Revision: 222038

URL: http://llvm.org/viewvc/llvm-project?rev=222038&view=rev
Log:
Change order of tablegen generated fast-isel instruction code to be
based on instruction complexity

The order that tablegen fast-isel instruction code is generated is
currently based on the text of the predicate (using string
less-than). This patch changes this to instead use the instruction
complexity. Because the complexities are not unique a C++ multimap is
used instead of a map.

This fixes the problem where code with no predicate always comes out
first (the empty string always compares as less than all other
strings) thus making the code with predicates dead code. See the FMUL
code in PPCFastISel.cpp for an example. It also more closely matches
the normal codegen ordering. Some error checking in the tablegen
fast-isel code is fixed as well.

Patch by Bill Seurer.


Modified:
    llvm/trunk/utils/TableGen/FastISelEmitter.cpp

Modified: llvm/trunk/utils/TableGen/FastISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FastISelEmitter.cpp?rev=222038&r1=222037&r2=222038&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/FastISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp Fri Nov 14 15:05:45 2014
@@ -37,6 +37,7 @@ struct InstructionMemo {
   const CodeGenRegisterClass *RC;
   std::string SubRegNo;
   std::vector<std::string>* PhysRegs;
+  std::string PredicateCheck;
 };
 } // End anonymous namespace
 
@@ -365,7 +366,9 @@ struct OperandsSignature {
 
 namespace {
 class FastISelMap {
-  typedef std::map<std::string, InstructionMemo> PredMap;
+  // A multimap is needed instead of a "plain" map because the key is 
+  // the instruction's complexity (an int) and they are not unique.
+  typedef std::multimap<int, InstructionMemo> PredMap;
   typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
   typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
   typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
@@ -374,6 +377,16 @@ class FastISelMap {
 
   OperandsOpcodeTypeRetPredMap SimplePatterns;
 
+  // This is used to check that there are no duplicate predicates            
+  typedef std::multimap<std::string, bool> PredCheckMap;
+  typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap;
+  typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap;
+  typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap;
+  typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap>
+            OperandsOpcodeTypeRetPredCheckMap;
+
+  OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck;
+
   std::map<OperandsSignature, std::vector<OperandsSignature> >
     SignaturesWithConstantForms;
 
@@ -385,6 +398,11 @@ public:
   void collectPatterns(CodeGenDAGPatterns &CGP);
   void printImmediatePredicates(raw_ostream &OS);
   void printFunctionDefinitions(raw_ostream &OS);
+private:  
+  void emitInstructionCode(raw_ostream &OS, 
+                           const OperandsSignature &Operands,
+                           const PredMap &PM, 
+                           const std::string &RetVTName);
 };
 } // End anonymous namespace
 
@@ -561,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGe
       Pattern.getDstPattern()->getOperator()->getName(),
       DstRC,
       SubRegNo,
-      PhysRegInputs
+      PhysRegInputs,
+      PredicateCheck
     };
+    
+    int complexity = Pattern.getPatternComplexity(CGP);
 
-    if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck))
+    if (SimplePatternsCheck[Operands][OpcodeName][VT]
+         [RetVT].count(PredicateCheck)) {
       PrintFatalError(Pattern.getSrcRecord()->getLoc(),
-                    "Duplicate record in FastISel table!");
+                    "Duplicate predicate in FastISel table!");
+    }
+    SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert(
+            std::make_pair(PredicateCheck, true));
 
-    SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;
+       // Note: Instructions with the same complexity will appear in the order
+          // that they are encountered.
+    SimplePatterns[Operands][OpcodeName][VT][RetVT].insert(
+      std::make_pair(complexity, Memo));
 
     // If any of the operands were immediates with predicates on them, strip
     // them down to a signature that doesn't have predicates so that we can
@@ -594,6 +622,72 @@ void FastISelMap::printImmediatePredicat
   OS << "\n\n";
 }
 
+void FastISelMap::emitInstructionCode(raw_ostream &OS, 
+                                      const OperandsSignature &Operands,
+                                      const PredMap &PM, 
+                                      const std::string &RetVTName) {
+  // Emit code for each possible instruction. There may be
+  // multiple if there are subtarget concerns.  A reverse iterator
+  // is used to produce the ones with highest complexity first.
+
+  bool OneHadNoPredicate = false;
+  for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();
+       PI != PE; ++PI) {
+    const InstructionMemo &Memo = PI->second;
+    std::string PredicateCheck = Memo.PredicateCheck;
+
+    if (PredicateCheck.empty()) {
+      assert(!OneHadNoPredicate &&
+             "Multiple instructions match and more than one had "
+             "no predicate!");
+      OneHadNoPredicate = true;
+    } else {
+      if (OneHadNoPredicate) {
+        // FIXME: This should be a PrintError once the x86 target
+        // fixes PR21575.
+        PrintWarning("Multiple instructions match and one with no "
+                     "predicate came before one with a predicate!  "
+                     "name:" + Memo.Name + "  predicate: " + 
+                     PredicateCheck);
+      }
+      OS << "  if (" + PredicateCheck + ") {\n";
+      OS << "  ";
+    }
+
+    for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+      if ((*Memo.PhysRegs)[i] != "")
+        OS << "  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
+           << "TII.get(TargetOpcode::COPY), "
+           << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+    }
+
+    OS << "  return fastEmitInst_";
+    if (Memo.SubRegNo.empty()) {
+      Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
+     ImmediatePredicates, true);
+      OS << "(" << InstNS << Memo.Name << ", ";
+      OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
+      if (!Operands.empty())
+        OS << ", ";
+      Operands.PrintArguments(OS, *Memo.PhysRegs);
+      OS << ");\n";
+    } else {
+      OS << "extractsubreg(" << RetVTName
+         << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
+    }
+
+    if (!PredicateCheck.empty()) {
+      OS << "  }\n";
+    }
+  }
+  // Return 0 if all of the possibilities had predicates but none
+  // were satisfied.
+  if (!OneHadNoPredicate)
+    OS << "  return 0;\n";
+  OS << "}\n";
+  OS << "\n";
+}
+
 
 void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
   // Now emit code for all the patterns that we collected.
@@ -620,7 +714,6 @@ void FastISelMap::printFunctionDefinitio
                RI != RE; ++RI) {
             MVT::SimpleValueType RetVT = RI->first;
             const PredMap &PM = RI->second;
-            bool HasPred = false;
 
             OS << "unsigned fastEmit_"
                << getLegalCName(Opcode)
@@ -631,54 +724,7 @@ void FastISelMap::printFunctionDefinitio
             Operands.PrintParameters(OS);
             OS << ") {\n";
 
-            // Emit code for each possible instruction. There may be
-            // multiple if there are subtarget concerns.
-            for (PredMap::const_iterator PI = PM.begin(), PE = PM.end();
-                 PI != PE; ++PI) {
-              std::string PredicateCheck = PI->first;
-              const InstructionMemo &Memo = PI->second;
-
-              if (PredicateCheck.empty()) {
-                assert(!HasPred &&
-                       "Multiple instructions match, at least one has "
-                       "a predicate and at least one doesn't!");
-              } else {
-                OS << "  if (" + PredicateCheck + ") {\n";
-                OS << "  ";
-                HasPred = true;
-              }
-
-              for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
-                if ((*Memo.PhysRegs)[i] != "")
-                  OS << "  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
-                     << "TII.get(TargetOpcode::COPY), "
-                     << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
-              }
-
-              OS << "  return fastEmitInst_";
-              if (Memo.SubRegNo.empty()) {
-                Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
-                                             ImmediatePredicates, true);
-                OS << "(" << InstNS << Memo.Name << ", ";
-                OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
-                if (!Operands.empty())
-                  OS << ", ";
-                Operands.PrintArguments(OS, *Memo.PhysRegs);
-                OS << ");\n";
-              } else {
-                OS << "extractsubreg(" << getName(RetVT);
-                OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
-              }
-
-              if (HasPred)
-                OS << "  }\n";
-
-            }
-            // Return 0 if none of the predicates were satisfied.
-            if (HasPred)
-              OS << "  return 0;\n";
-            OS << "}\n";
-            OS << "\n";
+            emitInstructionCode(OS, Operands, PM, getName(RetVT));
           }
 
           // Emit one function for the type that demultiplexes on return type.
@@ -720,58 +766,8 @@ void FastISelMap::printFunctionDefinitio
              << ")\n    return 0;\n";
 
           const PredMap &PM = RM.begin()->second;
-          bool HasPred = false;
-
-          // Emit code for each possible instruction. There may be
-          // multiple if there are subtarget concerns.
-          for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE;
-               ++PI) {
-            std::string PredicateCheck = PI->first;
-            const InstructionMemo &Memo = PI->second;
-
-            if (PredicateCheck.empty()) {
-              assert(!HasPred &&
-                     "Multiple instructions match, at least one has "
-                     "a predicate and at least one doesn't!");
-            } else {
-              OS << "  if (" + PredicateCheck + ") {\n";
-              OS << "  ";
-              HasPred = true;
-            }
-
-            for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
-              if ((*Memo.PhysRegs)[i] != "")
-                OS << "  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
-                   << "TII.get(TargetOpcode::COPY), "
-                   << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
-            }
-
-            OS << "  return fastEmitInst_";
-
-            if (Memo.SubRegNo.empty()) {
-              Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
-                                           ImmediatePredicates, true);
-              OS << "(" << InstNS << Memo.Name << ", ";
-              OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
-              if (!Operands.empty())
-                OS << ", ";
-              Operands.PrintArguments(OS, *Memo.PhysRegs);
-              OS << ");\n";
-            } else {
-              OS << "extractsubreg(RetVT, Op0, Op0IsKill, ";
-              OS << Memo.SubRegNo;
-              OS << ");\n";
-            }
-
-             if (HasPred)
-               OS << "  }\n";
-          }
 
-          // Return 0 if none of the predicates were satisfied.
-          if (HasPred)
-            OS << "  return 0;\n";
-          OS << "}\n";
-          OS << "\n";
+          emitInstructionCode(OS, Operands, PM, "RetVT");
         }
       }
 





More information about the llvm-commits mailing list