[llvm-commits] CVS: llvm/utils/TableGen/SimpleInstrSelEmitter.cpp SimpleInstrSelEmitter.h

Takahiro Kuba kuba at cs.uiuc.edu
Tue Apr 6 14:32:15 PDT 2004


Changes in directory llvm/utils/TableGen:

SimpleInstrSelEmitter.cpp added (r1.1)
SimpleInstrSelEmitter.h added (r1.1)

---
Log message:



Tablegen backend for really simple instruction selector



---
Diffs of the changes:  (+514 -0)

Index: llvm/utils/TableGen/SimpleInstrSelEmitter.cpp
diff -c /dev/null llvm/utils/TableGen/SimpleInstrSelEmitter.cpp:1.1
*** /dev/null	Tue Apr  6 14:31:42 2004
--- llvm/utils/TableGen/SimpleInstrSelEmitter.cpp	Tue Apr  6 14:31:31 2004
***************
*** 0 ****
--- 1,453 ----
+ //===- SimpleInstrSelEmitter.cpp - Generate a Simple Instruction Selector ------------===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ // This tablegen backend is responsible for emitting an instruction selector
+ // 
+ //
+ //===----------------------------------------------------------------------===//
+ #include "InstrInfoEmitter.h"
+ #include "SimpleInstrSelEmitter.h"
+ #include "CodeGenWrappers.h"
+ #include "Record.h"
+ #include "Support/Debug.h"
+ #include "Support/StringExtras.h"
+ #include <set>
+ 
+ 
+ #include "Record.h"
+ #include "Support/CommandLine.h"
+ #include "Support/Signals.h"
+ #include "Support/FileUtilities.h"
+ #include "CodeEmitterGen.h"
+ #include "RegisterInfoEmitter.h"
+ #include "InstrInfoEmitter.h"
+ #include "InstrSelectorEmitter.h"
+ #include "SimpleInstrSelEmitter.h"
+ #include <algorithm>
+ #include <cstdio>
+ #include <fstream>
+ #include <vector>
+ 
+ namespace llvm {
+ 
+   std::string FnDecs;
+ 
+ // run - Emit the main instruction description records for the target...
+ void SimpleInstrSelEmitter::run(std::ostream &OS) {
+ 
+ 
+   //  EmitSourceFileHeader("Mark's Instruction Selector for the X86 target", OS);
+ 
+ 
+ //   OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
+ 
+ //   OS << "#include \"llvm/Constants.h\"\n";
+ //   OS << "#include \"llvm/DerivedTypes.h\"\n";
+ //   OS << "#include \"llvm/Function.h\"\n";
+ //   OS << "#include \"llvm/Instructions.h\"\n";
+ //   OS << "#include \"llvm/IntrinsicLowering.h\"\n";
+ //   OS << "#include \"llvm/Pass.h\"\n";
+ //   OS << "#include \"llvm/CodeGen/MachineConstantPool.h\"\n";
+ //   OS << "#include \"llvm/CodeGen/MachineFrameInfo.h\"\n";
+ //   OS << "#include \"llvm/CodeGen/MachineFunction.h\"\n";
+ //   OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
+ //   OS << "#include \"llvm/CodeGen/SSARegMap.h\"\n";
+ //   OS << "#include \"llvm/Target/MRegisterInfo.h\"\n";
+ //   OS << "#include \"llvm/Target/TargetMachine.h\"\n";
+ //   OS << "#include \"llvm/Support/InstVisitor.h\"\n";
+ 
+ //  OS << "using namespace llvm;\n\n";
+ 
+ 
+   FnDecs = "";
+ 
+   // for each InstrClass
+ 
+   std::vector<Record*> Recs = Records.getAllDerivedDefinitions("InstrClass");
+   for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
+     std::string InstrClassName = Recs[i]->getName();
+     OS << "// Generate BMI instructions for " << InstrClassName << "\n\n";
+     OS << "void ISel::visit";
+     OS << Recs[i]->getValueAsString("FunctionName");
+     OS << "(" <<  Recs[i]->getValueAsString("InstructionName") << " &I)\n{" << "\n";
+     // for each supported InstrSubclass
+ 
+     OS << spacing() << "unsigned DestReg = getReg(I);\n";
+     OS << spacing() << "unsigned Op0Reg  = getReg(I.getOperand(0));\n";
+     OS << spacing() << "unsigned Op1Reg  = getReg(I.getOperand(1));\n";
+     OS << spacing() << "Value   *Op0Val  = I.getOperand(0);\n";
+     OS << spacing() << "Value   *Op1Val  = I.getOperand(1);\n";
+ 
+     OS << spacing() << "MachineBasicBlock::iterator IP = BB->end();\n";
+ 
+     OS << std::endl;
+ 
+     ListInit *SupportedSubclasses = Recs[i]->getValueAsListInit("Supports");
+ 
+     //OS << spacing() << InstrClassName << "Prep();" << "\n";
+     //FnDecs += "void ISel::" + InstrClassName + "Prep() {\n\n}\n\n";
+ 
+     std::vector<std::string> vi;
+ 
+     // generate subclasses nested switch statements
+     InstrSubclasses(OS, InstrClassName, InstrClassName, SupportedSubclasses, vi, 0);
+ 
+     //OS << spacing() << InstrClassName << "Post();\n";
+     //FnDecs += "void ISel::" + InstrClassName + "Post() {\n\n}\n\n";
+ 
+     OS << "}\n";
+     OS << "\n\n\n";
+ 
+   } // for each instrclass
+ 
+   //  OS << "} //namespace\n";
+ 
+ 
+ #if 0
+   // print out function stubs
+   OS << "\n\n\n//Functions\n\n" << FnDecs;
+ 
+   // print out getsubclass() definitions
+   std::vector<Record*> SubclassColRec = Records.getAllDerivedDefinitions("InstrSubclassCollection");
+   for (unsigned j=0, m=SubclassColRec.getSize(); j!=m; ++j) {
+     std::string SubclassName = SubclassColRec[j]->getName();
+     FnDecs += "unsigned ISel::get" + SubclassName + "() {\n\n";
+ 
+     ListInit* list = dynamic_cast<ListInit*>(SubclassColRec[j].getValueAsListInit("List"));
+     
+     for (unsigned k=0; n=list.getSize(); k!=n; ++k) {
+ 
+     FnDecs += "}\n\n";
+   }
+ #endif
+ 
+ } //run
+ 
+   
+ 
+ // find instructions that match all the subclasses (only support for 1 now)
+ Record* SimpleInstrSelEmitter::findInstruction(std::ostream &OS, std::string cl, std::vector<std::string>& vi) {
+   std::vector<Record*> Recs = Records.getAllDerivedDefinitions("TargInstrSet");
+ 
+   for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
+     Record* thisClass = Recs[i]->getValueAsDef("Class");
+ 
+     if (thisClass->getName() == cl) {
+ 
+       // get the Subclasses this supports
+       ListInit* SubclassList = Recs[i]->getValueAsListInit("List");
+ 
+       bool Match = true;
+ 
+       if (SubclassList->getSize() != vi.size())
+ 	Match = false;
+       
+       // match the instruction's supported subclasses with the subclasses we are looking for
+ 
+       for (unsigned j=0, f=SubclassList->getSize(); j!=f; ++j) {
+ 	DefInit* SubclassDef = dynamic_cast<DefInit*>(SubclassList->getElement(j));
+ 	Record* thisSubclass = SubclassDef->getDef();
+ 
+ 	std::string searchingFor = vi[j];
+ 
+ 	if (thisSubclass->getName() != searchingFor) {
+ 	  Match = false;
+ 	}
+ 
+       } // for each subclass list
+ 
+       if (Match == true) { return Recs[i]; }
+   
+     } //if instrclass matches
+ 
+   } // for all instructions
+ 
+   // if no instructions found, return NULL
+   return NULL;
+ 
+ } //findInstruction
+   
+ 
+ 
+ Record* SimpleInstrSelEmitter::findRegister(std::ostream &OS, std::string regname) {
+   std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Register");
+ 
+   for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
+     Record* thisReg = Recs[i];
+ 
+     if (thisReg->getName() == regname) return Recs[i];
+   }
+   
+   return NULL;
+ 
+ }
+ 
+ // handle "::" and "+" etc
+ std::string SimpleInstrSelEmitter::formatRegister(std::ostream &OS, std::string regname) {
+   std::string Reg;
+   std::string suffix;
+ 
+   int x = std::strcspn(regname.c_str(),"+-");
+ 
+   // operate on text before "+" or "-", append it back at the end
+   Reg = regname.substr(0,x);
+   suffix = regname.substr(x,regname.length());
+ 
+   unsigned int y = std::strcspn(Reg.c_str(),":");
+ 
+   if (y == Reg.length()) { // does not contain "::"
+     
+     Record* RegRec = findRegister(OS,Reg);
+ 
+     assert(RegRec && "Register not found!");
+ 
+     if (RegRec->getValueAsString("Namespace") != "Virtual") {
+       Reg = RegRec->getValueAsString("Namespace") + "::" + RegRec->getName();
+     } else {
+       Reg = RegRec->getName();
+     }
+   } // regular case
+ 
+   // append + or - at the end again (i.e. X86::EAX+1)
+   Reg = Reg + suffix;
+ 
+   return Reg;
+ }
+ 
+ 
+ // take information in the instruction class and generate the correct BMI call
+ void SimpleInstrSelEmitter::generateBMIcall(std::ostream &OS, std::string MBB, std::string IP, std::string Opcode, int NumOperands, ListInit &instroperands, ListInit &operands) {
+ 
+   // find Destination Register
+   StringInit* DestRegStr = dynamic_cast<StringInit*>(operands.getElement(0));
+   std::string DestReg = formatRegister(OS,DestRegStr->getValue());
+ 
+   OS << "BuildMI(";
+   OS << MBB << ", ";
+   OS << IP << ", ";
+   OS << Opcode << ", ";
+   OS << NumOperands;
+ 
+   if (DestReg != "Pseudo") {
+     OS << ", " << DestReg << ")";
+   } else {
+     OS << ")";
+   }
+   
+   // handle the .add stuff
+   for (unsigned i=0, e=instroperands.getSize(); i!=e; ++i) {
+     DefInit* OpDef = dynamic_cast<DefInit*>(instroperands.getElement(i));
+     StringInit* RegStr = dynamic_cast<StringInit*>(operands.getElement(i+1));
+ 
+     Record* Op = OpDef->getDef();
+ 
+     std::string opstr = Op->getValueAsString("Name");
+ 
+     std::string regname;
+ 
+     if (opstr == "Register") {
+       regname = formatRegister(OS,RegStr->getValue());
+     } else {
+       regname = RegStr->getValue();
+     }
+ 
+     OS << ".add" << opstr << "(" << regname << ")";
+   }
+   
+   OS << ";\n";
+   
+ } //generateBMIcall
+ 
+   
+  std::string SimpleInstrSelEmitter::spacing() {
+    return globalSpacing;
+  }
+ 
+  std::string SimpleInstrSelEmitter::addspacing() {
+    globalSpacing += "  ";
+    return globalSpacing;
+  }
+ 
+  std::string SimpleInstrSelEmitter::remspacing() {
+    globalSpacing = globalSpacing.substr(0,globalSpacing.length()-2);
+    return globalSpacing;
+  }
+ 
+ 
+  // recursively print out the subclasses of an instruction
+  //
+  void SimpleInstrSelEmitter::InstrSubclasses(std::ostream &OS, std::string prefix, std::string InstrClassName, ListInit* SupportedSubclasses, std::vector<std::string>& vi, unsigned depth) {
+ 
+    
+    if (depth >= SupportedSubclasses->getSize()) {
+       return;
+    }
+ 
+    // get the subclass collection
+    
+    DefInit* InstrSubclassColl = dynamic_cast<DefInit*>(SupportedSubclasses->getElement(depth));
+ 
+    Record* InstrSubclassRec = InstrSubclassColl->getDef();
+ 
+    std::string SubclassName = InstrSubclassRec->getName();
+    
+    
+    if (InstrSubclassRec->getValueAsString("PreCode") != "") {
+      //	  OS << spacing() << prefix << "_" << Subclass->getName() << "_Prep();\n";
+      OS << spacing() << InstrSubclassRec->getValueAsString("PreCode") << "\n\n";
+    }
+    
+    
+    OS << spacing() << "// Looping through " << SubclassName << "\n";
+    
+    OS << spacing() << "switch (" <<  SubclassName <<") {\n";
+    addspacing();
+    
+    ListInit* SubclassList = InstrSubclassRec->getValueAsListInit("List");
+    
+    for (unsigned k=0, g = SubclassList->getSize(); k!=g; ++k) {
+      
+      DefInit* SubclassDef = dynamic_cast<DefInit*>(SubclassList->getElement(k));
+      
+      Record* Subclass = SubclassDef->getDef();
+      
+      OS << spacing() << "// " << prefix << "_" << Subclass->getName() << "\n";
+      OS << spacing() << "case " << Subclass->getName() << ":\n";
+      addspacing();
+      OS << spacing() << "{\n";
+      
+      
+      vi.push_back(Subclass->getName());
+      
+      // go down hierarchy
+      InstrSubclasses(OS, prefix + "_" + Subclass->getName(), InstrClassName, SupportedSubclasses, vi, depth+1);
+      
+      // find the record that matches this
+      Record *theInstructionSet = findInstruction(OS, InstrClassName, vi);
+      
+      // only print out the assertion if this is a leaf
+      if ( (theInstructionSet == NULL) && (depth == (SupportedSubclasses->getSize() - 1)) ) {
+        
+        OS << spacing() << "assert(0 && \"No instructions defined for " << InstrClassName << " instructions of subclasses " << prefix << "_" << Subclass->getName() << "!\");" << "\n";
+        
+      } else if (theInstructionSet != NULL) {
+        
+        if (theInstructionSet->getValueAsString("PreCode") != "") {
+ 	 OS << spacing() << theInstructionSet->getValueAsString("PreCode") << "\n\n";
+        }
+        
+        ListInit *theInstructions = theInstructionSet->getValueAsListInit("Instructions");
+        
+        ListInit *registerlists = theInstructionSet->getValueAsListInit("Operands"); // not necessarily registers anymore, but the name will stay for now
+        
+        for (unsigned l=0, h=theInstructions->getSize(); l!=h; ++l) {
+ 	 
+ 	 DefInit *theInstructionDef = dynamic_cast<DefInit*>(theInstructions->getElement(l));
+ 	 Record *theInstruction = theInstructionDef->getDef();
+ 	 
+ 	 ListInit *operands = theInstruction->getValueAsListInit("Params");
+ 	 
+ 	 OS << spacing();
+ 	 
+ 	 ListInit* registers = dynamic_cast<ListInit*>(registerlists->getElement(l));
+ 	 
+ 	 // handle virtual instructions here before going to generateBMIcall
+ 	 
+ 	 if (theInstruction->getValueAsString("Namespace") == "Virtual") {
+ 	   
+ 	   // create reg for different sizes
+ 	   std::string Instr = theInstruction->getName();
+ 	   StringInit* DestRegInit = dynamic_cast<StringInit*>(registers->getElement(0));
+ 	   std::string DestReg = DestRegInit->getValue();
+ 	   std::string theType;
+ 	   
+ 	   if (Instr == "NullInstruction") { } // do nothing
+ 	   else if (Instr == "CreateRegByte")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SByteTy);\n";
+ 	   else if (Instr == "CreateRegShort")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SShortTy);\n";
+ 	   else if (Instr == "CreateRegInt")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SIntTy);\n";
+ 	   else if (Instr == "CreateRegLong")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SLongTy);\n";
+ 	   else if (Instr == "CreateRegUByte")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UByteTy);\n";
+ 	   else if (Instr == "CreateRegUShort")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UShortTy);\n";
+ 	   else if (Instr == "CreateRegUInt")
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::UIntTy);\n";
+ 	   else if (Instr == "CreateRegULong") 
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::ULongTy);\n";
+ 	   else if (Instr == "CreateRegFloat") 
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::FloatTy);\n";
+ 	   else if (Instr == "CreateRegDouble") 
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::DoubleTy);\n";
+ 	   else if (Instr == "CreateRegPointer") 
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::PointerTy_;\n";
+ 	   else 
+ 	     OS << "unsigned " << DestReg << " = makeAnotherReg(Type::SByteTy);\n"; // create a byte by default
+ 	   
+ 	   
+ 	 } else {
+ 	   std::string InstrName;
+ 	   
+ 	   if (theInstruction->getValueAsString("Namespace") != "Virtual") {
+ 	     InstrName = theInstruction->getValueAsString("Namespace") + "::" + theInstruction->getValueAsString("Name");
+ 	   } else {
+ 	     // shouldn't ever happen, virtual instrs should be caught before this
+ 	     InstrName = theInstruction->getValueAsString("Name");
+ 	   }
+ 	   
+ 	   generateBMIcall(OS, "*BB","IP",InstrName,theInstruction->getValueAsInt("NumOperands"),*operands,*registers);
+ 	 }
+ 	 
+        }
+        
+        if (theInstructionSet->getValueAsString("PostCode") != "") {
+ 	 OS << spacing() << theInstructionSet->getValueAsString("PostCode") << "\n\n";
+        }
+        
+      }
+      
+      
+      
+      if (InstrSubclassRec->getValueAsString("PostCode") != "") {
+        //OS << spacing() << "// " << prefix << "_" << Subclass->getName() << "_Prep();\n";
+        OS << spacing() << InstrSubclassRec->getValueAsString("PostCode") << "\n\n";
+      }
+      
+      
+      OS << spacing() << "break;\n";
+ 
+      OS << spacing() << "}\n\n";
+      
+      remspacing();
+      
+      vi.pop_back();
+    }
+    
+    // provide a default case for the switch
+    
+    OS << spacing() << "default:\n";
+    OS << spacing() << "  assert(0 && \"No instructions defined for " << InstrClassName << " instructions of subclasses " << prefix << "_" << SubclassName << "!\");" << "\n";
+    OS << spacing() << "  break;\n\n";
+    
+    remspacing();
+    OS << spacing() << "}\n";
+    
+  }
+ 
+ 
+  // ret br switch invoke unwind
+  // add sub mul div rem setcc (eq ne lt gt le ge)
+  // and or xor sbl sbr
+  // malloc free alloca load store
+  // getelementptr phi cast call vanext vaarg
+  
+ } // End llvm namespace


Index: llvm/utils/TableGen/SimpleInstrSelEmitter.h
diff -c /dev/null llvm/utils/TableGen/SimpleInstrSelEmitter.h:1.1
*** /dev/null	Tue Apr  6 14:31:42 2004
--- llvm/utils/TableGen/SimpleInstrSelEmitter.h	Tue Apr  6 14:31:31 2004
***************
*** 0 ****
--- 1,61 ----
+ //===- SimpleInstrSelEmitter.h - Generate a Simple Instruction Selector ----*- C++ -*-===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ // This tablegen backend is responsible for emitting a simple instruction selector
+ // 
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef SIMPLE_INSTR_SELECTOR_EMITTER_H
+ #define SIMPLE_INSTR_SELECTOR_EMITTER_H
+ 
+ #include "TableGenBackend.h"
+ #include "CodeGenWrappers.h"
+ #include <vector>
+ #include <map>
+ #include <cassert>
+ 
+ namespace llvm {
+ 
+ class Init;
+ class InstrSelectorEmitter;
+ 
+ 
+ /// InstrSelectorEmitter - The top-level class which coordinates construction
+ /// and emission of the instruction selector.
+ ///
+ class SimpleInstrSelEmitter : public TableGenBackend {
+   RecordKeeper &Records;
+   std::string globalSpacing;
+ 
+ public:
+   SimpleInstrSelEmitter(RecordKeeper &R) : Records(R) {globalSpacing = "  ";}
+   
+   // run - Output the instruction set description, returning true on failure.
+   void run(std::ostream &OS);
+ 
+   Record* SimpleInstrSelEmitter::findInstruction(std::ostream &OS, std::string cl, std::vector<std::string>& vi);
+ 
+   Record* SimpleInstrSelEmitter::findRegister(std::ostream &OS, std::string regname);
+ 
+   std::string SimpleInstrSelEmitter::formatRegister(std::ostream &OS, std::string regname);
+ 
+   void SimpleInstrSelEmitter::generateBMIcall(std::ostream &OS, std::string MBB, std::string IP, std::string Opcode, int NumOperands, ListInit &l, ListInit &r);
+ 
+   void SimpleInstrSelEmitter::InstrSubclasses(std::ostream &OS, std::string prefix, std::string InstrClassName, ListInit* SupportedSubclasses, std::vector<std::string>& vi, unsigned depth);
+ 
+   std::string spacing();
+   std::string addspacing();
+   std::string remspacing();
+ 
+ };
+ 
+ } // End llvm namespace
+ 
+ #endif





More information about the llvm-commits mailing list