Factor out the predicate check code from DAGISelEmitter.cpp
authorDan Gohman <gohman@apple.com>
Fri, 22 Aug 2008 00:20:26 +0000 (00:20 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 22 Aug 2008 00:20:26 +0000 (00:20 +0000)
and use it in FastISelEmitter.cpp, and make FastISel
subtarget aware. Among other things, this lets it work
properly on x86 targets that don't have SSE, where it
successfully selects x87 instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55156 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/FastISel.h
lib/CodeGen/SelectionDAG/FastISel.cpp
lib/Target/X86/X86FastISel.cpp
test/CodeGen/X86/fast-isel.ll
utils/TableGen/CodeGenDAGPatterns.cpp
utils/TableGen/CodeGenDAGPatterns.h
utils/TableGen/DAGISelEmitter.cpp
utils/TableGen/FastISelEmitter.cpp

index cd6a6d61996e77cc550aeaceaf945450a3227781..c414956bb552e5253ca2522b1b4b9e577bde67e7 100644 (file)
@@ -26,18 +26,21 @@ class MachineRegisterInfo;
 class TargetData;
 class TargetInstrInfo;
 class TargetLowering;
+class TargetMachine;
 class TargetRegisterClass;
 
 /// FastISel - This is a fast-path instruction selection class that
 /// generates poor code and doesn't support illegal types or non-trivial
 /// lowering, but runs quickly.
 class FastISel {
+protected:
   MachineBasicBlock *MBB;
   MachineFunction &MF;
   MachineRegisterInfo &MRI;
+  const TargetMachine &TM;
   const TargetData &TD;
   const TargetInstrInfo &TII;
-  TargetLowering &TLI;
+  const TargetLowering &TLI;
 
 public:
   /// SelectInstructions - Do "fast" instruction selection over the
index 450596e50d01f605713bd79b6034ed78df3a99f5..388028334d579eace822f808e7b5ce9fb7e31572 100644 (file)
@@ -220,10 +220,12 @@ FastISel::SelectInstructions(BasicBlock::iterator Begin,
 }
 
 FastISel::FastISel(MachineFunction &mf)
-  : MF(mf), MRI(mf.getRegInfo()),
-    TD(*mf.getTarget().getTargetData()),
-    TII(*mf.getTarget().getInstrInfo()),
-    TLI(*mf.getTarget().getTargetLowering()) {
+  : MF(mf),
+    MRI(mf.getRegInfo()),
+    TM(mf.getTarget()),
+    TD(*TM.getTargetData()),
+    TII(*TM.getInstrInfo()),
+    TLI(*TM.getTargetLowering()) {
 }
 
 FastISel::~FastISel() {}
index 0c0660c7832271315cddbe04b9001f578d919a17..f049a4d363de5b1757297d66c25393f273528403 100644 (file)
@@ -17,4 +17,5 @@
 #include "X86RegisterInfo.h"
 #include "X86ISelLowering.h"
 #include "X86FastISel.h"
+#include "X86TargetMachine.h"
 #include "X86GenFastISel.inc"
index 3510024fe4f972c7c1b415c22f9229110653df0d..601e38578c6f58db67d9f2341eab1054f477d3d6 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -fast-isel -march=x86 -mattr=sse2
+; RUN: llvm-as < %s | llc -fast-isel -march=x86
 
 ; This tests very minimal fast-isel functionality.
 
index 1e957834a883c5810741f4b82b5ba66589b802a3..1e595dd4744a9e68390531118a8ed310ce7a4790 100644 (file)
@@ -140,6 +140,33 @@ void DumpDepVars(MultipleUseVarSet &DepVars) {
 }
 }
 
+//===----------------------------------------------------------------------===//
+// PatternToMatch implementation
+//
+
+/// getPredicateCheck - Return a single string containing all of this
+/// pattern's predicates concatenated with "&&" operators.
+///
+std::string PatternToMatch::getPredicateCheck() const {
+  std::string PredicateCheck;
+  for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
+    if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
+      Record *Def = Pred->getDef();
+      if (!Def->isSubClassOf("Predicate")) {
+#ifndef NDEBUG
+        Def->dump();
+#endif
+        assert(0 && "Unknown predicate type!");
+      }
+      if (!PredicateCheck.empty())
+        PredicateCheck += " && ";
+      PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
+    }
+  }
+
+  return PredicateCheck;
+}
+
 //===----------------------------------------------------------------------===//
 // SDTypeConstraint implementation
 //
index 4434cf0c1c152c920b611661a92a192fd26153f0..4d7ea58b06bab60bd2ed4ab9f1e47b7e3a3b31ad 100644 (file)
@@ -444,6 +444,8 @@ struct PatternToMatch {
   TreePatternNode *getDstPattern() const { return DstPattern; }
   const std::vector<Record*> &getDstRegs() const { return Dstregs; }
   unsigned         getAddedComplexity() const { return AddedComplexity; }
+
+  std::string getPredicateCheck() const;
 };
 
   
index 12667d5656f757263c24f2a63cda637e243b6fe5..cf4d20f9c6753e3544d9b07e5b997eeb07d89022 100644 (file)
@@ -317,7 +317,7 @@ private:
   CodeGenDAGPatterns &CGP;
 
   // Predicates.
-  ListInit *Predicates;
+  std::string PredicateCheck;
   // Pattern cost.
   unsigned Cost;
   // Instruction selector pattern.
@@ -395,7 +395,7 @@ private:
     VTNo++;
   }
 public:
-  PatternCodeEmitter(CodeGenDAGPatterns &cgp, ListInit *preds,
+  PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck,
                      TreePatternNode *pattern, TreePatternNode *instr,
                      std::vector<std::pair<unsigned, std::string> > &gc,
                      std::set<std::string> &gd,
@@ -403,7 +403,7 @@ public:
                      std::vector<std::string> &tv,
                      bool &oiv,
                      unsigned &niro)
-  : CGP(cgp), Predicates(preds), Pattern(pattern), Instruction(instr),
+  : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr),
     GeneratedCode(gc), GeneratedDecl(gd),
     TargetOpcodes(to), TargetVTs(tv),
     OutputIsVariadic(oiv), NumInputRootOps(niro),
@@ -431,22 +431,6 @@ public:
       if (DisablePatternForFastISel(N, CGP))
         emitCheck("!Fast");
 
-      std::string PredicateCheck;
-      for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
-        if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
-          Record *Def = Pred->getDef();
-          if (!Def->isSubClassOf("Predicate")) {
-#ifndef NDEBUG
-            Def->dump();
-#endif
-            assert(0 && "Unknown predicate type!");
-          }
-          if (!PredicateCheck.empty())
-            PredicateCheck += " && ";
-          PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
-        }
-      }
-      
       emitCheck(PredicateCheck);
     }
 
@@ -1412,7 +1396,7 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
   OutputIsVariadic = false;
   NumInputRootOps = 0;
 
-  PatternCodeEmitter Emitter(CGP, Pattern.getPredicates(),
+  PatternCodeEmitter Emitter(CGP, Pattern.getPredicateCheck(),
                              Pattern.getSrcPattern(), Pattern.getDstPattern(),
                              GeneratedCode, GeneratedDecl,
                              TargetOpcodes, TargetVTs,
index cbe77f6d5dff0db20733555fa3896fc6e87ca843..b343013b06711f3eebbe75914adcad67136aa99a 100644 (file)
@@ -175,10 +175,11 @@ void FastISelEmitter::run(std::ostream &OS) {
   OS << "namespace " << InstNS.substr(0, InstNS.size() - 2) << " {\n";
   OS << "\n";
   
-  typedef std::map<MVT::SimpleValueType, InstructionMemo> TypeMap;
-  typedef std::map<std::string, TypeMap> OpcodeTypeMap;
-  typedef std::map<OperandsSignature, OpcodeTypeMap> OperandsOpcodeTypeMap;
-  OperandsOpcodeTypeMap SimplePatterns;
+  typedef std::map<std::string, InstructionMemo> PredMap;
+  typedef std::map<MVT::SimpleValueType, PredMap> TypePredMap;
+  typedef std::map<std::string, TypePredMap> OpcodeTypePredMap;
+  typedef std::map<OperandsSignature, OpcodeTypePredMap> OperandsOpcodeTypePredMap;
+  OperandsOpcodeTypePredMap SimplePatterns;
 
   for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
        E = CGP.ptm_end(); I != E; ++I) {
@@ -230,27 +231,32 @@ void FastISelEmitter::run(std::ostream &OS) {
     if (!Operands.initialize(InstPatNode, Target, VT, DstRC))
       continue;
 
+    // Get the predicate that guards this pattern.
+    std::string PredicateCheck = Pattern.getPredicateCheck();
+
     // Ok, we found a pattern that we can handle. Remember it.
     InstructionMemo Memo = {
       Pattern.getDstPattern()->getOperator()->getName(),
       DstRC
     };
-    SimplePatterns[Operands][OpcodeName][VT] = Memo;
+    assert(!SimplePatterns[Operands][OpcodeName][VT].count(PredicateCheck) &&
+           "Duplicate pattern!");
+    SimplePatterns[Operands][OpcodeName][VT][PredicateCheck] = Memo;
   }
 
   // Declare the target FastISel class.
   OS << "class FastISel : public llvm::FastISel {\n";
-  for (OperandsOpcodeTypeMap::const_iterator OI = SimplePatterns.begin(),
+  for (OperandsOpcodeTypePredMap::const_iterator OI = SimplePatterns.begin(),
        OE = SimplePatterns.end(); OI != OE; ++OI) {
     const OperandsSignature &Operands = OI->first;
-    const OpcodeTypeMap &OTM = OI->second;
+    const OpcodeTypePredMap &OTM = OI->second;
 
-    for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end();
+    for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
          I != E; ++I) {
       const std::string &Opcode = I->first;
-      const TypeMap &TM = I->second;
+      const TypePredMap &TM = I->second;
 
-      for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end();
+      for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
            TI != TE; ++TI) {
         MVT::SimpleValueType VT = TI->first;
 
@@ -279,8 +285,19 @@ void FastISelEmitter::run(std::ostream &OS) {
     Operands.PrintParameters(OS);
     OS << ");\n";
   }
+  OS << "\n";
+
+  // Declare the Subtarget member, which is used for predicate checks.
+  OS << "  const " << InstNS.substr(0, InstNS.size() - 2)
+     << "Subtarget *Subtarget;\n";
+  OS << "\n";
+
+  // Declare the constructor.
   OS << "public:\n";
-  OS << "  explicit FastISel(MachineFunction &mf) : llvm::FastISel(mf) {}\n";
+  OS << "  explicit FastISel(MachineFunction &mf)\n";
+  OS << "     : llvm::FastISel(mf),\n";
+  OS << "       Subtarget(&TM.getSubtarget<" << InstNS.substr(0, InstNS.size() - 2)
+     << "Subtarget>()) {}\n";
   OS << "};\n";
   OS << "\n";
 
@@ -291,25 +308,26 @@ void FastISelEmitter::run(std::ostream &OS) {
   OS << "\n";
 
   // Now emit code for all the patterns that we collected.
-  for (OperandsOpcodeTypeMap::const_iterator OI = SimplePatterns.begin(),
+  for (OperandsOpcodeTypePredMap::const_iterator OI = SimplePatterns.begin(),
        OE = SimplePatterns.end(); OI != OE; ++OI) {
     const OperandsSignature &Operands = OI->first;
-    const OpcodeTypeMap &OTM = OI->second;
+    const OpcodeTypePredMap &OTM = OI->second;
 
-    for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end();
+    for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
          I != E; ++I) {
       const std::string &Opcode = I->first;
-      const TypeMap &TM = I->second;
+      const TypePredMap &TM = I->second;
 
       OS << "// FastEmit functions for " << Opcode << ".\n";
       OS << "\n";
 
       // Emit one function for each opcode,type pair.
-      for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end();
+      for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
            TI != TE; ++TI) {
         MVT::SimpleValueType VT = TI->first;
-        const InstructionMemo &Memo = TI->second;
-  
+        const PredMap &PM = TI->second;
+        bool HasPred = false;
+
         OS << "unsigned FastISel::FastEmit_"
            << getLegalCName(Opcode)
            << "_" << getLegalCName(getName(VT)) << "_";
@@ -317,14 +335,34 @@ void FastISelEmitter::run(std::ostream &OS) {
         OS << "(";
         Operands.PrintParameters(OS);
         OS << ") {\n";
-        OS << "  return FastEmitInst_";
-        Operands.PrintManglingSuffix(OS);
-        OS << "(" << InstNS << Memo.Name << ", ";
-        OS << InstNS << Memo.RC->getName() << "RegisterClass";
-        if (!Operands.empty())
-          OS << ", ";
-        Operands.PrintArguments(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;
+          }
+          OS << "  return FastEmitInst_";
+          Operands.PrintManglingSuffix(OS);
+          OS << "(" << InstNS << Memo.Name << ", ";
+          OS << InstNS << Memo.RC->getName() << "RegisterClass";
+          if (!Operands.empty())
+            OS << ", ";
+          Operands.PrintArguments(OS);
+          OS << ");\n";
+        }
+        // Return 0 if none of the predicates were satisfied.
+        if (HasPred)
+          OS << "  return 0;\n";
         OS << "}\n";
         OS << "\n";
       }
@@ -339,7 +377,7 @@ void FastISelEmitter::run(std::ostream &OS) {
       Operands.PrintParameters(OS);
       OS << ") {\n";
       OS << "  switch (VT) {\n";
-      for (TypeMap::const_iterator TI = TM.begin(), TE = TM.end();
+      for (TypePredMap::const_iterator TI = TM.begin(), TE = TM.end();
            TI != TE; ++TI) {
         MVT::SimpleValueType VT = TI->first;
         std::string TypeName = getName(VT);
@@ -366,7 +404,7 @@ void FastISelEmitter::run(std::ostream &OS) {
     Operands.PrintParameters(OS);
     OS << ") {\n";
     OS << "  switch (Opcode) {\n";
-    for (OpcodeTypeMap::const_iterator I = OTM.begin(), E = OTM.end();
+    for (OpcodeTypePredMap::const_iterator I = OTM.begin(), E = OTM.end();
          I != E; ++I) {
       const std::string &Opcode = I->first;