diff options
Diffstat (limited to 'utils')
61 files changed, 2408 insertions, 1149 deletions
diff --git a/utils/DSAextract.py b/utils/DSAextract.py index 134e945..89dece1 100644 --- a/utils/DSAextract.py +++ b/utils/DSAextract.py @@ -58,7 +58,7 @@ node_set = set() #read the file one line at a time buffer = input.readline() while buffer != '': - #filter out the unecessary checks on all the edge lines + #filter out the unnecessary checks on all the edge lines if not arrowexp.search(buffer): #check to see if this is a node we are looking for for regexp in regexp_list: diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 5d4cb0c..f225594 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -131,26 +131,34 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { } // Paren value #0 is for the fully matched string. Any new parenthesized - // values add from their. + // values add from there. unsigned CurParen = 1; // Otherwise, there is at least one regex piece. Build up the regex pattern // by escaping scary characters in fixed strings, building up one big regex. while (!PatternStr.empty()) { // RegEx matches. - if (PatternStr.size() >= 2 && - PatternStr[0] == '{' && PatternStr[1] == '{') { + if (PatternStr.startswith("{{")) { // Otherwise, this is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), - "found start of regex string with no end '}}'", "error"); + "found start of regex string with no end '}}'","error"); return true; } + // Enclose {{}} patterns in parens just like [[]] even though we're not + // capturing the result for any purpose. This is required in case the + // expression contains an alternation like: CHECK: abc{{x|z}}def. We + // want this to turn into: "abc(x|z)def" not "abcx|zdef". + RegExStr += '('; + ++CurParen; + if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) return true; + RegExStr += ')'; + PatternStr = PatternStr.substr(End+2); continue; } @@ -160,8 +168,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { // second form is [[foo]] which is a reference to foo. The variable name // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. - if (PatternStr.size() >= 2 && - PatternStr[0] == '[' && PatternStr[1] == '[') { + if (PatternStr.startswith("[[")) { // Verify that it is terminated properly. size_t End = PatternStr.find("]]"); if (End == StringRef::npos) { @@ -185,10 +192,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { // Verify that the name is well formed. for (unsigned i = 0, e = Name.size(); i != e; ++i) - if (Name[i] != '_' && - (Name[i] < 'a' || Name[i] > 'z') && - (Name[i] < 'A' || Name[i] > 'Z') && - (Name[i] < '0' || Name[i] > '9')) { + if (Name[i] != '_' && !isalnum(Name[i])) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), "invalid name in named regex", "error"); return true; diff --git a/utils/KillTheDoctor/KillTheDoctor.cpp b/utils/KillTheDoctor/KillTheDoctor.cpp index 7a89dd3..1ddae0b 100644 --- a/utils/KillTheDoctor/KillTheDoctor.cpp +++ b/utils/KillTheDoctor/KillTheDoctor.cpp @@ -169,14 +169,14 @@ namespace { static error_code GetFileNameFromHandle(HANDLE FileHandle, std::string& Name) { char Filename[MAX_PATH+1]; - bool Sucess = false; + bool Success = false; Name.clear(); // Get the file size. LARGE_INTEGER FileSize; - Sucess = ::GetFileSizeEx(FileHandle, &FileSize); + Success = ::GetFileSizeEx(FileHandle, &FileSize); - if (!Sucess) + if (!Success) return windows_error(::GetLastError()); // Create a file mapping object. @@ -198,12 +198,12 @@ static error_code GetFileNameFromHandle(HANDLE FileHandle, if (!MappedFile) return windows_error(::GetLastError()); - Sucess = ::GetMappedFileNameA(::GetCurrentProcess(), + Success = ::GetMappedFileNameA(::GetCurrentProcess(), MappedFile, Filename, array_lengthof(Filename) - 1); - if (!Sucess) + if (!Success) return windows_error(::GetLastError()); else { Name = Filename; diff --git a/utils/NewNightlyTest.pl b/utils/NewNightlyTest.pl index 1b48168..da806e9 100755 --- a/utils/NewNightlyTest.pl +++ b/utils/NewNightlyTest.pl @@ -794,7 +794,7 @@ my %hash_of_data = ( 'endtime' => $endtime, 'target_triple' => $targetTriple, - # Unused, but left around for backwards compatability. + # Unused, but left around for backwards compatibility. 'warnings' => "", 'cvsusercommitlist' => "", 'cvsuserupdatelist' => "", diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index e48ac1e..62bd1c6 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -607,7 +607,7 @@ void ARMFilter::recurse() { for (bitIndex = 0; bitIndex < NumBits; bitIndex++) BitValueArray[StartBit + bitIndex] = BIT_UNSET; - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( (unsigned)-1, @@ -639,7 +639,7 @@ void ARMFilter::recurse() { BitValueArray[StartBit + bitIndex] = BIT_FALSE; } - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // category of instructions. FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( mapIterator->first, @@ -1624,6 +1624,10 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; + // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg. + if (Name == "tBX_RET" || Name == "tBX_RET_vararg") + return false; + // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. if (Name == "tTPsoft" || Name == "t2TPsoft") return false; @@ -1648,6 +1652,11 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") return false; + // FIXME: Use ldr.n to work around a Darwin assembler bug. + // Introduce a workaround with tLDRpciDIS opcode. + if (Name == "tLDRpci") + return false; + // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST. if (Name == "t2LDRDpci") return false; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 369ec90..1d7a67b 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -88,7 +88,7 @@ // 2. The operand matcher will try every possible entry with the same // mnemonic and will check if the target feature for this mnemonic also // matches. After that, if the operand to be matched has its index -// present in the mask, a successfull match occurs. Otherwise, fallback +// present in the mask, a successful match occurs. Otherwise, fallback // to the regular operand parsing. // // 3. For a match success, each operand class that has a 'ParserMethod' @@ -258,7 +258,7 @@ public: return ValueName < RHS.ValueName; default: - // This class preceeds the RHS if it is a proper subset of the RHS. + // This class precedes the RHS if it is a proper subset of the RHS. if (isSubsetOf(RHS)) return true; if (RHS.isSubsetOf(*this)) @@ -896,8 +896,8 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // Gather the defined sets. for (std::vector<CodeGenRegisterClass>::const_iterator it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(std::set<Record*>(it->Elements.begin(), - it->Elements.end())); + RegisterSets.insert(std::set<Record*>(it->getOrder().begin(), + it->getOrder().end())); // Add any required singleton sets. for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), @@ -971,8 +971,8 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // Name the register classes which correspond to a user defined RegisterClass. for (std::vector<CodeGenRegisterClass>::const_iterator it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { - ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(), - it->Elements.end())]; + ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->getOrder().begin(), + it->getOrder().end())]; if (CI->ValueName.empty()) { CI->ClassName = it->getName(); CI->Name = "MCK_" + it->getName(); @@ -1265,7 +1265,7 @@ void AsmMatcherInfo::BuildInfo() { II->BuildAliasResultOperands(); } - // Reorder classes so that classes preceed super classes. + // Reorder classes so that classes precede super classes. std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); } @@ -1538,7 +1538,7 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, // operand from the earlier one.We can only tie single MCOperand values. //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); unsigned TiedOp = OpInfo.TiedOperandNum; - assert(i > TiedOp && "Tied operand preceeds its target!"); + assert(i > TiedOp && "Tied operand precedes its target!"); CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; Signature += "__Tie" + utostr(TiedOp); break; @@ -2321,7 +2321,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; OS << " if (i + 1 >= Operands.size()) {\n"; OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; - OS << " break;"; + OS << " break;\n"; OS << " }\n"; OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n"; OS << " continue;\n"; diff --git a/utils/TableGen/AsmMatcherEmitter.h b/utils/TableGen/AsmMatcherEmitter.h index 729c938..c13adf3 100644 --- a/utils/TableGen/AsmMatcherEmitter.h +++ b/utils/TableGen/AsmMatcherEmitter.h @@ -16,8 +16,6 @@ #define ASMMATCHER_EMITTER_H #include "TableGenBackend.h" -#include <map> -#include <vector> #include <cassert> namespace llvm { diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 05bc113..818053a 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -670,8 +670,8 @@ public: for (std::map<StringRef, unsigned>::iterator I = OpMap.begin(), E = OpMap.end(); I != E; ++I) - O.indent(6) << "OpMap[\"" << I->first << "\"] = " - << I->second << ";\n"; + O.indent(6) << "OpMap.push_back(std::make_pair(\"" << I->first << "\", " + << I->second << "));\n"; O.indent(6) << "break;\n"; O.indent(4) << '}'; @@ -754,6 +754,20 @@ static void EmitComputeAvailableFeatures(AsmWriterInfo &Info, O << "}\n\n"; } +static void EmitGetMapOperandNumber(raw_ostream &O) { + O << "static unsigned getMapOperandNumber(" + << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n"; + O << " StringRef Name) {\n"; + O << " for (SmallVectorImpl<std::pair<StringRef, unsigned> >::" + << "const_iterator\n"; + O << " I = OpMap.begin(), E = OpMap.end(); I != E; ++I)\n"; + O << " if (I->first == Name)\n"; + O << " return I->second;\n"; + O << " assert(false && \"Operand not in map!\");\n"; + O << " return 0;\n"; + O << "}\n\n"; +} + void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { CodeGenTarget Target(Records); @@ -791,16 +805,16 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { O << " case RC_" << Name << ":\n"; // Emit the register list now. - unsigned IE = RC.Elements.size(); + unsigned IE = RC.getOrder().size(); if (IE == 1) { - O << " if (Reg == " << getQualifiedName(RC.Elements[0]) << ")\n"; + O << " if (Reg == " << getQualifiedName(RC.getOrder()[0]) << ")\n"; O << " return true;\n"; } else { O << " switch (Reg) {\n"; O << " default: break;\n"; for (unsigned II = 0; II != IE; ++II) { - Record *Reg = RC.Elements[II]; + Record *Reg = RC.getOrder()[II]; O << " case " << getQualifiedName(Reg) << ":\n"; } @@ -816,10 +830,46 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { O << "}\n\n"; } +static unsigned CountNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split(' '); + + while (!ASM.second.empty()) { + ++NumOps; + ASM = ASM.second.split(' '); + } + + return NumOps; +} + +static unsigned CountResultNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); + + if (!ASM.second.empty()) { + size_t I = ASM.second.find('{'); + StringRef Str = ASM.second; + if (I != StringRef::npos) + Str = ASM.second.substr(I, ASM.second.find('|', I)); + + ASM = Str.split(' '); + + do { + ++NumOps; + ASM = ASM.second.split(' '); + } while (!ASM.second.empty()); + } + + return NumOps; +} + void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); + if (!AsmWriter->getValueAsBit("isMCAsmWriter")) + return; + O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; @@ -828,9 +878,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); - const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; - std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); @@ -840,6 +887,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); const Record *R = *I; + if (!R->getValueAsBit("EmitAlias")) + continue; // We were told not to emit the alias, but to emit the aliasee. const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator()); AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); @@ -857,13 +906,18 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (std::vector<CodeGenInstAlias*>::iterator II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { const CodeGenInstAlias *CGA = *II; + unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + unsigned NumResultOps = + CountResultNumOperands(CGA->ResultInst->AsmString); + + // Don't emit the alias if it has more operands than what it's aliasing. + if (NumResultOps < CountNumOperands(CGA->AsmString)) + continue; + IAPrinter *IAP = new IAPrinter(AWI, CGA->Result->getAsString(), CGA->AsmString); - IAP->addReqFeatures(CGA->TheDef->getValueAsListOfDefs("Predicates")); - unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); - std::string Cond; Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); IAP->addCond(Cond); @@ -898,7 +952,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } } else { assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); - // FIXME: We need to handle these situations. + // FIXME: We may need to handle these situations. delete IAP; IAP = 0; CantHandle = true; @@ -932,9 +986,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { EmitSubtargetFeatureFlagEnumeration(AWI, O); EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O); - O << "bool " << Target.getName() << ClassName - << "::printAliasInstr(const " << MachineInstrClassName - << " *MI, raw_ostream &OS) {\n"; + std::string Header; + raw_string_ostream HeaderO(Header); + + HeaderO << "bool " << Target.getName() << ClassName + << "::printAliasInstr(const MCInst" + << " *MI, raw_ostream &OS) {\n"; std::string Cases; raw_string_ostream CasesO(Cases); @@ -973,22 +1030,26 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { CasesO << '\n'; } - CasesO.indent(4) << "return true;\n"; + CasesO.indent(4) << "return false;\n"; } - if (CasesO.str().empty() || !isMC) { - O << " return true;\n"; + if (CasesO.str().empty()) { + O << HeaderO.str(); + O << " return false;\n"; O << "}\n\n"; O << "#endif // PRINT_ALIAS_INSTR\n"; return; } + EmitGetMapOperandNumber(O); + + O << HeaderO.str(); O.indent(2) << "StringRef AsmString;\n"; - O.indent(2) << "std::map<StringRef, unsigned> OpMap;\n"; + O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n"; if (NeedAvailableFeatures) O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n"; O.indent(2) << "switch (MI->getOpcode()) {\n"; - O.indent(2) << "default: return true;\n"; + O.indent(2) << "default: return false;\n"; O << CasesO.str(); O.indent(2) << "}\n\n"; @@ -1010,14 +1071,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " *I == '_'))\n"; O << " ++I;\n"; O << " StringRef Name(Start, I - Start);\n"; - O << " printOperand(MI, OpMap[Name], OS);\n"; + O << " printOperand(MI, getMapOperandNumber(OpMap, Name), OS);\n"; O << " } else {\n"; O << " OS << *I++;\n"; O << " }\n"; O << " }\n"; O << " }\n\n"; - O << " return false;\n"; + O << " return true;\n"; O << "}\n\n"; O << "#endif // PRINT_ALIAS_INSTR\n"; diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 514b191..a24c921 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -16,6 +16,7 @@ add_llvm_utility(tblgen CodeEmitterGen.cpp CodeGenDAGPatterns.cpp CodeGenInstruction.cpp + CodeGenRegisters.cpp CodeGenTarget.cpp DAGISelEmitter.cpp DAGISelMatcherEmitter.cpp @@ -34,6 +35,7 @@ add_llvm_utility(tblgen OptParserEmitter.cpp Record.cpp RegisterInfoEmitter.cpp + SetTheory.cpp StringMatcher.cpp SubtargetEmitter.cpp TGLexer.cpp diff --git a/utils/TableGen/CallingConvEmitter.h b/utils/TableGen/CallingConvEmitter.h index 7fc2507..431c33b 100644 --- a/utils/TableGen/CallingConvEmitter.h +++ b/utils/TableGen/CallingConvEmitter.h @@ -16,8 +16,6 @@ #define CALLINGCONV_EMITTER_H #include "TableGenBackend.h" -#include <map> -#include <vector> #include <cassert> namespace llvm { diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp index 187ab46..d9d5a3c 100644 --- a/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/utils/TableGen/ClangASTNodesEmitter.cpp @@ -155,10 +155,13 @@ void ClangDeclContextEmitter::run(raw_ostream &OS) { } } - for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end(); - i != e; ++i) { - OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; - } + // To keep identical order, RecordVector may be used + // instead of RecordSet. + for (RecordVector::iterator + i = DeclContextsVector.begin(), e = DeclContextsVector.end(); + i != e; ++i) + if (DeclContexts.find(*i) != DeclContexts.end()) + OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; OS << "#undef DECL_CONTEXT\n"; OS << "#undef DECL_CONTEXT_BASE\n"; diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index 60e67c4..0a48e75 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -18,9 +18,11 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" -#include <set> #include <map> +#include <algorithm> +#include <functional> using namespace llvm; //===----------------------------------------------------------------------===// @@ -121,7 +123,6 @@ namespace { } // end anonymous namespace. - //===----------------------------------------------------------------------===// // Warning Tables (.inc file) generation. //===----------------------------------------------------------------------===// @@ -162,7 +163,7 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { OS << ", \""; OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"'; } else { - OS << ", 0"; + OS << ", \"\""; } // SFINAE bit @@ -179,6 +180,14 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); + + // Brief + OS << ", \""; + OS.write_escaped(R.getValueAsString("Brief")) << '"'; + + // Explanation + OS << ", \""; + OS.write_escaped(R.getValueAsString("Explanation")) << '"'; OS << ")\n"; } } @@ -187,6 +196,15 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Warning Group Tables generation //===----------------------------------------------------------------------===// +static std::string getDiagCategoryEnum(llvm::StringRef name) { + if (name.empty()) + return "DiagCat_None"; + llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_"); + for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I) + enumName += isalnum(*I) ? *I : '_'; + return enumName.str(); +} + namespace { struct GroupInfo { std::vector<const Record*> DiagsInGroup; @@ -267,7 +285,9 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { // Group option string. - OS << " { \""; + OS << " { "; + OS << I->first.size() << ", "; + OS << "\""; OS.write_escaped(I->first) << "\"," << std::string(MaxLen-I->first.size()+1, ' '); @@ -291,6 +311,52 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << "\n#ifdef GET_CATEGORY_TABLE\n"; for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(), E = CategoriesByID.end(); I != E; ++I) - OS << "CATEGORY(\"" << *I << "\")\n"; + OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; } + +//===----------------------------------------------------------------------===// +// Diagnostic name index generation +//===----------------------------------------------------------------------===// + +namespace { +struct RecordIndexElement +{ + RecordIndexElement() {} + explicit RecordIndexElement(Record const &R): + Name(R.getName()) {} + + std::string Name; +}; + +struct RecordIndexElementSorter : + public std::binary_function<RecordIndexElement, RecordIndexElement, bool> { + + bool operator()(RecordIndexElement const &Lhs, + RecordIndexElement const &Rhs) const { + return Lhs.Name < Rhs.Name; + } + +}; + +} // end anonymous namespace. + +void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) { + const std::vector<Record*> &Diags = + Records.getAllDerivedDefinitions("Diagnostic"); + + std::vector<RecordIndexElement> Index; + Index.reserve(Diags.size()); + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { + const Record &R = *(Diags[i]); + Index.push_back(RecordIndexElement(R)); + } + + std::sort(Index.begin(), Index.end(), RecordIndexElementSorter()); + + for (unsigned i = 0, e = Index.size(); i != e; ++i) { + const RecordIndexElement &R = Index[i]; + + OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; + } +} diff --git a/utils/TableGen/ClangDiagnosticsEmitter.h b/utils/TableGen/ClangDiagnosticsEmitter.h index edd062a..1e4c8b7 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.h +++ b/utils/TableGen/ClangDiagnosticsEmitter.h @@ -33,13 +33,21 @@ public: }; class ClangDiagGroupsEmitter : public TableGenBackend { - RecordKeeper &Records; + RecordKeeper &Records; public: explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {} void run(raw_ostream &OS); }; +class ClangDiagsIndexNameEmitter : public TableGenBackend { + RecordKeeper &Records; +public: + explicit ClangDiagsIndexNameEmitter(RecordKeeper &R) : Records(R) {} + + void run(raw_ostream &OS); +}; + } // End llvm namespace diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 957dd19..9d4dc5c4 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -63,10 +63,14 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { // return the variable bit position. Otherwise return -1. int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI, int bit) { - if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) + if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) { if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable())) if (VI->getName() == VarName) return VBI->getBitNum(); + } else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) { + if (VI->getName() == VarName) + return 0; + } return -1; } diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 79cf18a..a08cde6 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -580,34 +580,29 @@ typedef std::map<std::string, int> DepVarMap; /// Const iterator shorthand for DepVarMap typedef DepVarMap::const_iterator DepVarMap_citer; -namespace { -void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { +static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { if (N->isLeaf()) { - if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) { + if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) DepMap[N->getName()]++; - } } else { for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) FindDepVarsOf(N->getChild(i), DepMap); } } - -//! Find dependent variables within child patterns -/*! - */ -void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { + +/// Find dependent variables within child patterns +static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { DepVarMap depcounts; FindDepVarsOf(N, depcounts); for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) { - if (i->second > 1) { // std::pair<std::string, int> + if (i->second > 1) // std::pair<std::string, int> DepVars.insert(i->first); - } } } -//! Dump the dependent variable set: #ifndef NDEBUG -void DumpDepVars(MultipleUseVarSet &DepVars) { +/// Dump the dependent variable set: +static void DumpDepVars(MultipleUseVarSet &DepVars) { if (DepVars.empty()) { DEBUG(errs() << "<empty set>"); } else { @@ -621,6 +616,66 @@ void DumpDepVars(MultipleUseVarSet &DepVars) { } #endif + +//===----------------------------------------------------------------------===// +// TreePredicateFn Implementation +//===----------------------------------------------------------------------===// + +/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. +TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { + assert((getPredCode().empty() || getImmCode().empty()) && + ".td file corrupt: can't have a node predicate *and* an imm predicate"); +} + +std::string TreePredicateFn::getPredCode() const { + return PatFragRec->getRecord()->getValueAsCode("PredicateCode"); +} + +std::string TreePredicateFn::getImmCode() const { + return PatFragRec->getRecord()->getValueAsCode("ImmediateCode"); +} + + +/// isAlwaysTrue - Return true if this is a noop predicate. +bool TreePredicateFn::isAlwaysTrue() const { + return getPredCode().empty() && getImmCode().empty(); +} + +/// Return the name to use in the generated code to reference this, this is +/// "Predicate_foo" if from a pattern fragment "foo". +std::string TreePredicateFn::getFnName() const { + return "Predicate_" + PatFragRec->getRecord()->getName(); +} + +/// getCodeToRunOnSDNode - Return the code for the function body that +/// evaluates this predicate. The argument is expected to be in "Node", +/// not N. This handles casting and conversion to a concrete node type as +/// appropriate. +std::string TreePredicateFn::getCodeToRunOnSDNode() const { + // Handle immediate predicates first. + std::string ImmCode = getImmCode(); + if (!ImmCode.empty()) { + std::string Result = + " int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();\n"; + return Result + ImmCode; + } + + // Handle arbitrary node predicates. + assert(!getPredCode().empty() && "Don't have any predicate code!"); + std::string ClassName; + if (PatFragRec->getOnlyTree()->isLeaf()) + ClassName = "SDNode"; + else { + Record *Op = PatFragRec->getOnlyTree()->getOperator(); + ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName(); + } + std::string Result; + if (ClassName == "SDNode") + Result = " SDNode *N = Node;\n"; + else + Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + + return Result + getPredCode(); } //===----------------------------------------------------------------------===// @@ -1015,7 +1070,7 @@ void TreePatternNode::print(raw_ostream &OS) const { } for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) - OS << "<<P:" << PredicateFns[i] << ">>"; + OS << "<<P:" << PredicateFns[i].getFnName() << ">>"; if (TransformFn) OS << "<<X:" << TransformFn->getName() << ">>"; if (!getName().empty()) @@ -1150,9 +1205,9 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); - std::string Code = Op->getValueAsCode("Predicate"); - if (!Code.empty()) - FragTree->addPredicateFn("Predicate_"+Op->getName()); + TreePredicateFn PredFn(Frag); + if (!PredFn.isAlwaysTrue()) + FragTree->addPredicateFn(PredFn); // Resolve formal arguments to their actual value. if (Frag->getNumArgs()) { @@ -2063,9 +2118,9 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // If there is a code init for this fragment, keep track of the fact that // this fragment uses it. - std::string Code = Fragments[i]->getValueAsCode("Predicate"); - if (!Code.empty()) - P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName()); + TreePredicateFn PredFn(P); + if (!PredFn.isAlwaysTrue()) + P->getOnlyTree()->addPredicateFn(PredFn); // If there is a node transformation corresponding to this, keep track of // it. diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 946dcee..e4e8574 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -239,6 +239,57 @@ public: return MadeChange; } }; + +/// TreePredicateFn - This is an abstraction that represents the predicates on +/// a PatFrag node. This is a simple one-word wrapper around a pointer to +/// provide nice accessors. +class TreePredicateFn { + /// PatFragRec - This is the TreePattern for the PatFrag that we + /// originally came from. + TreePattern *PatFragRec; +public: + /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. + TreePredicateFn(TreePattern *N); + + + TreePattern *getOrigPatFragRecord() const { return PatFragRec; } + + /// isAlwaysTrue - Return true if this is a noop predicate. + bool isAlwaysTrue() const; + + bool isImmediatePattern() const { return !getImmCode().empty(); } + + /// getImmediatePredicateCode - Return the code that evaluates this pattern if + /// this is an immediate predicate. It is an error to call this on a + /// non-immediate pattern. + std::string getImmediatePredicateCode() const { + std::string Result = getImmCode(); + assert(!Result.empty() && "Isn't an immediate pattern!"); + return Result; + } + + + bool operator==(const TreePredicateFn &RHS) const { + return PatFragRec == RHS.PatFragRec; + } + + bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); } + + /// Return the name to use in the generated code to reference this, this is + /// "Predicate_foo" if from a pattern fragment "foo". + std::string getFnName() const; + + /// getCodeToRunOnSDNode - Return the code for the function body that + /// evaluates this predicate. The argument is expected to be in "Node", + /// not N. This handles casting and conversion to a concrete node type as + /// appropriate. + std::string getCodeToRunOnSDNode() const; + +private: + std::string getPredCode() const; + std::string getImmCode() const; +}; + /// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped /// patterns), and as such should be ref counted. We currently just leak all @@ -263,7 +314,7 @@ class TreePatternNode { /// PredicateFns - The predicate functions to execute on this node to check /// for a match. If this list is empty, no predicate is involved. - std::vector<std::string> PredicateFns; + std::vector<TreePredicateFn> PredicateFns; /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. @@ -323,14 +374,18 @@ public: return false; } - const std::vector<std::string> &getPredicateFns() const {return PredicateFns;} + bool hasAnyPredicate() const { return !PredicateFns.empty(); } + + const std::vector<TreePredicateFn> &getPredicateFns() const { + return PredicateFns; + } void clearPredicateFns() { PredicateFns.clear(); } - void setPredicateFns(const std::vector<std::string> &Fns) { + void setPredicateFns(const std::vector<TreePredicateFn> &Fns) { assert(PredicateFns.empty() && "Overwriting non-empty predicate list!"); PredicateFns = Fns; } - void addPredicateFn(const std::string &Fn) { - assert(!Fn.empty() && "Empty predicate string!"); + void addPredicateFn(const TreePredicateFn &Fn) { + assert(!Fn.isAlwaysTrue() && "Empty predicate string!"); if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) == PredicateFns.end()) PredicateFns.push_back(Fn); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 5b0aedf..73fe916 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -417,7 +417,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, if (!InstOpRec->isSubClassOf("RegisterClass")) return false; - if (!T.getRegisterClass(InstOpRec).containsRegister(ADI->getDef())) + if (!T.getRegisterClass(InstOpRec) + .contains(T.getRegBank().getReg(ADI->getDef()))) throw TGError(Loc, "fixed register " +ADI->getDef()->getName() + " is not a member of the " + InstOpRec->getName() + " register class!"); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 6d2d8fb..5f1e0be 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -137,6 +137,7 @@ namespace llvm { bool isVariadic; // Provide transparent accessors to the operand list. + bool empty() const { return OperandList.empty(); } unsigned size() const { return OperandList.size(); } const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } OperandInfo &operator[](unsigned i) { return OperandList[i]; } diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 3208c0d..3f6ba61 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -69,6 +69,9 @@ namespace llvm { /// isCommutative - True if the intrinsic is commutative. bool isCommutative; + + /// canThrow - True if the intrinsic can throw. + bool canThrow; enum ArgAttribute { NoCapture diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp new file mode 100644 index 0000000..37952fc --- /dev/null +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -0,0 +1,493 @@ +//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines structures to encapsulate information gleaned from the +// target register and register class definitions. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenRegisters.h" +#include "CodeGenTarget.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// CodeGenRegister +//===----------------------------------------------------------------------===// + +CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum) + : TheDef(R), + EnumValue(Enum), + CostPerUse(R->getValueAsInt("CostPerUse")), + SubRegsComplete(false) +{} + +const std::string &CodeGenRegister::getName() const { + return TheDef->getName(); +} + +namespace { + struct Orphan { + CodeGenRegister *SubReg; + Record *First, *Second; + Orphan(CodeGenRegister *r, Record *a, Record *b) + : SubReg(r), First(a), Second(b) {} + }; +} + +const CodeGenRegister::SubRegMap & +CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { + // Only compute this map once. + if (SubRegsComplete) + return SubRegs; + SubRegsComplete = true; + + std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs"); + std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); + if (SubList.size() != Indices.size()) + throw TGError(TheDef->getLoc(), "Register " + getName() + + " SubRegIndices doesn't match SubRegs"); + + // First insert the direct subregs and make sure they are fully indexed. + for (unsigned i = 0, e = SubList.size(); i != e; ++i) { + CodeGenRegister *SR = RegBank.getReg(SubList[i]); + if (!SubRegs.insert(std::make_pair(Indices[i], SR)).second) + throw TGError(TheDef->getLoc(), "SubRegIndex " + Indices[i]->getName() + + " appears twice in Register " + getName()); + } + + // Keep track of inherited subregs and how they can be reached. + SmallVector<Orphan, 8> Orphans; + + // Clone inherited subregs and place duplicate entries on Orphans. + // Here the order is important - earlier subregs take precedence. + for (unsigned i = 0, e = SubList.size(); i != e; ++i) { + CodeGenRegister *SR = RegBank.getReg(SubList[i]); + const SubRegMap &Map = SR->getSubRegs(RegBank); + + // Add this as a super-register of SR now all sub-registers are in the list. + // This creates a topological ordering, the exact order depends on the + // order getSubRegs is called on all registers. + SR->SuperRegs.push_back(this); + + for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; + ++SI) { + if (!SubRegs.insert(*SI).second) + Orphans.push_back(Orphan(SI->second, Indices[i], SI->first)); + + // Noop sub-register indexes are possible, so avoid duplicates. + if (SI->second != SR) + SI->second->SuperRegs.push_back(this); + } + } + + // Process the composites. + ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices"); + for (unsigned i = 0, e = Comps->size(); i != e; ++i) { + DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); + if (!Pat) + throw TGError(TheDef->getLoc(), "Invalid dag '" + + Comps->getElement(i)->getAsString() + + "' in CompositeIndices"); + DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); + if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) + throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + + Pat->getAsString()); + + // Resolve list of subreg indices into R2. + CodeGenRegister *R2 = this; + for (DagInit::const_arg_iterator di = Pat->arg_begin(), + de = Pat->arg_end(); di != de; ++di) { + DefInit *IdxInit = dynamic_cast<DefInit*>(*di); + if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) + throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + + Pat->getAsString()); + const SubRegMap &R2Subs = R2->getSubRegs(RegBank); + SubRegMap::const_iterator ni = R2Subs.find(IdxInit->getDef()); + if (ni == R2Subs.end()) + throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() + + " refers to bad index in " + R2->getName()); + R2 = ni->second; + } + + // Insert composite index. Allow overriding inherited indices etc. + SubRegs[BaseIdxInit->getDef()] = R2; + + // R2 is no longer an orphan. + for (unsigned j = 0, je = Orphans.size(); j != je; ++j) + if (Orphans[j].SubReg == R2) + Orphans[j].SubReg = 0; + } + + // Now Orphans contains the inherited subregisters without a direct index. + // Create inferred indexes for all missing entries. + for (unsigned i = 0, e = Orphans.size(); i != e; ++i) { + Orphan &O = Orphans[i]; + if (!O.SubReg) + continue; + SubRegs[RegBank.getCompositeSubRegIndex(O.First, O.Second, true)] = + O.SubReg; + } + return SubRegs; +} + +void +CodeGenRegister::addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const { + assert(SubRegsComplete && "Must precompute sub-registers"); + std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) { + CodeGenRegister *SR = SubRegs.find(Indices[i])->second; + if (OSet.insert(SR)) + SR->addSubRegsPreOrder(OSet); + } +} + +//===----------------------------------------------------------------------===// +// CodeGenRegisterClass +//===----------------------------------------------------------------------===// + +CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) + : TheDef(R) { + // Rename anonymous register classes. + if (R->getName().size() > 9 && R->getName()[9] == '.') { + static unsigned AnonCounter = 0; + R->setName("AnonRegClass_"+utostr(AnonCounter++)); + } + + std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); + for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { + Record *Type = TypeList[i]; + if (!Type->isSubClassOf("ValueType")) + throw "RegTypes list member '" + Type->getName() + + "' does not derive from the ValueType class!"; + VTs.push_back(getValueType(Type)); + } + assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); + + Elements = RegBank.getSets().expand(R); + for (unsigned i = 0, e = Elements->size(); i != e; ++i) + Members.insert(RegBank.getReg((*Elements)[i])); + + // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. + ListInit *SRC = R->getValueAsListInit("SubRegClasses"); + for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { + DagInit *DAG = dynamic_cast<DagInit*>(*i); + if (!DAG) throw "SubRegClasses must contain DAGs"; + DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator()); + Record *RCRec; + if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass")) + throw "Operator '" + DAG->getOperator()->getAsString() + + "' in SubRegClasses is not a RegisterClass"; + // Iterate over args, all SubRegIndex instances. + for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end(); + ai != ae; ++ai) { + DefInit *Idx = dynamic_cast<DefInit*>(*ai); + Record *IdxRec; + if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex")) + throw "Argument '" + (*ai)->getAsString() + + "' in SubRegClasses is not a SubRegIndex"; + if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second) + throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice"; + } + } + + // Allow targets to override the size in bits of the RegisterClass. + unsigned Size = R->getValueAsInt("Size"); + + Namespace = R->getValueAsString("Namespace"); + SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); + SpillAlignment = R->getValueAsInt("Alignment"); + CopyCost = R->getValueAsInt("CopyCost"); + Allocatable = R->getValueAsBit("isAllocatable"); + MethodBodies = R->getValueAsCode("MethodBodies"); + MethodProtos = R->getValueAsCode("MethodProtos"); +} + +bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { + return Members.count(Reg); +} + +// Returns true if RC is a strict subclass. +// RC is a sub-class of this class if it is a valid replacement for any +// instruction operand where a register of this classis required. It must +// satisfy these conditions: +// +// 1. All RC registers are also in this. +// 2. The RC spill size must not be smaller than our spill size. +// 3. RC spill alignment must be compatible with ours. +// +bool CodeGenRegisterClass::hasSubClass(const CodeGenRegisterClass *RC) const { + return SpillAlignment && RC->SpillAlignment % SpillAlignment == 0 && + SpillSize <= RC->SpillSize && + std::includes(Members.begin(), Members.end(), + RC->Members.begin(), RC->Members.end()); +} + +const std::string &CodeGenRegisterClass::getName() const { + return TheDef->getName(); +} + +//===----------------------------------------------------------------------===// +// CodeGenRegBank +//===----------------------------------------------------------------------===// + +CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { + // Configure register Sets to understand register classes. + Sets.addFieldExpander("RegisterClass", "MemberList"); + + // Read in the user-defined (named) sub-register indices. + // More indices will be synthesized later. + SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); + std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord()); + NumNamedIndices = SubRegIndices.size(); + + // Read in the register definitions. + std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); + std::sort(Regs.begin(), Regs.end(), LessRecord()); + Registers.reserve(Regs.size()); + // Assign the enumeration values. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + Registers.push_back(CodeGenRegister(Regs[i], i + 1)); + + // Read in register class definitions. + std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); + if (RCs.empty()) + throw std::string("No 'RegisterClass' subclasses defined!"); + + RegClasses.reserve(RCs.size()); + for (unsigned i = 0, e = RCs.size(); i != e; ++i) + RegClasses.push_back(CodeGenRegisterClass(*this, RCs[i])); +} + +CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { + if (Def2Reg.empty()) + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + Def2Reg[Registers[i].TheDef] = &Registers[i]; + + if (CodeGenRegister *Reg = Def2Reg[Def]) + return Reg; + + throw TGError(Def->getLoc(), "Not a known Register!"); +} + +CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { + if (Def2RC.empty()) + for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) + Def2RC[RegClasses[i].TheDef] = &RegClasses[i]; + + if (CodeGenRegisterClass *RC = Def2RC[Def]) + return RC; + + throw TGError(Def->getLoc(), "Not a known RegisterClass!"); +} + +Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B, + bool create) { + // Look for an existing entry. + Record *&Comp = Composite[std::make_pair(A, B)]; + if (Comp || !create) + return Comp; + + // None exists, synthesize one. + std::string Name = A->getName() + "_then_" + B->getName(); + Comp = new Record(Name, SMLoc(), Records); + Records.addDef(Comp); + SubRegIndices.push_back(Comp); + return Comp; +} + +unsigned CodeGenRegBank::getSubRegIndexNo(Record *idx) { + std::vector<Record*>::const_iterator i = + std::find(SubRegIndices.begin(), SubRegIndices.end(), idx); + assert(i != SubRegIndices.end() && "Not a SubRegIndex"); + return (i - SubRegIndices.begin()) + 1; +} + +void CodeGenRegBank::computeComposites() { + // Precompute all sub-register maps. This will create Composite entries for + // all inferred sub-register indices. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + Registers[i].getSubRegs(*this); + + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg1 = &Registers[i]; + const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), + e1 = SRM1.end(); i1 != e1; ++i1) { + Record *Idx1 = i1->first; + CodeGenRegister *Reg2 = i1->second; + // Ignore identity compositions. + if (Reg1 == Reg2) + continue; + const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(); + // Try composing Idx1 with another SubRegIndex. + for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(), + e2 = SRM2.end(); i2 != e2; ++i2) { + std::pair<Record*, Record*> IdxPair(Idx1, i2->first); + CodeGenRegister *Reg3 = i2->second; + // Ignore identity compositions. + if (Reg2 == Reg3) + continue; + // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. + for (CodeGenRegister::SubRegMap::const_iterator i1d = SRM1.begin(), + e1d = SRM1.end(); i1d != e1d; ++i1d) { + if (i1d->second == Reg3) { + std::pair<CompositeMap::iterator, bool> Ins = + Composite.insert(std::make_pair(IdxPair, i1d->first)); + // Conflicting composition? Emit a warning but allow it. + if (!Ins.second && Ins.first->second != i1d->first) { + errs() << "Warning: SubRegIndex " << getQualifiedName(Idx1) + << " and " << getQualifiedName(IdxPair.second) + << " compose ambiguously as " + << getQualifiedName(Ins.first->second) << " or " + << getQualifiedName(i1d->first) << "\n"; + } + } + } + } + } + } + + // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid + // compositions, so remove any mappings of that form. + for (CompositeMap::iterator i = Composite.begin(), e = Composite.end(); + i != e;) { + CompositeMap::iterator j = i; + ++i; + if (j->first.second == j->second) + Composite.erase(j); + } +} + +// Compute sets of overlapping registers. +// +// The standard set is all super-registers and all sub-registers, but the +// target description can add arbitrary overlapping registers via the 'Aliases' +// field. This complicates things, but we can compute overlapping sets using +// the following rules: +// +// 1. The relation overlap(A, B) is reflexive and symmetric but not transitive. +// +// 2. overlap(A, B) implies overlap(A, S) for all S in supers(B). +// +// Alternatively: +// +// overlap(A, B) iff there exists: +// A' in { A, subregs(A) } and B' in { B, subregs(B) } such that: +// A' = B' or A' in aliases(B') or B' in aliases(A'). +// +// Here subregs(A) is the full flattened sub-register set returned by +// A.getSubRegs() while aliases(A) is simply the special 'Aliases' field in the +// description of register A. +// +// This also implies that registers with a common sub-register are considered +// overlapping. This can happen when forming register pairs: +// +// P0 = (R0, R1) +// P1 = (R1, R2) +// P2 = (R2, R3) +// +// In this case, we will infer an overlap between P0 and P1 because of the +// shared sub-register R1. There is no overlap between P0 and P2. +// +void CodeGenRegBank:: +computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map) { + assert(Map.empty()); + + // Collect overlaps that don't follow from rule 2. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = &Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + + // Reg overlaps itself. + Overlaps.insert(Reg); + + // All super-registers overlap. + const CodeGenRegister::SuperRegList &Supers = Reg->getSuperRegs(); + Overlaps.insert(Supers.begin(), Supers.end()); + + // Form symmetrical relations from the special Aliases[] lists. + std::vector<Record*> RegList = Reg->TheDef->getValueAsListOfDefs("Aliases"); + for (unsigned i2 = 0, e2 = RegList.size(); i2 != e2; ++i2) { + CodeGenRegister *Reg2 = getReg(RegList[i2]); + CodeGenRegister::Set &Overlaps2 = Map[Reg2]; + const CodeGenRegister::SuperRegList &Supers2 = Reg2->getSuperRegs(); + // Reg overlaps Reg2 which implies it overlaps supers(Reg2). + Overlaps.insert(Reg2); + Overlaps.insert(Supers2.begin(), Supers2.end()); + Overlaps2.insert(Reg); + Overlaps2.insert(Supers.begin(), Supers.end()); + } + } + + // Apply rule 2. and inherit all sub-register overlaps. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = &Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM.begin(), + e2 = SRM.end(); i2 != e2; ++i2) { + CodeGenRegister::Set &Overlaps2 = Map[i2->second]; + Overlaps.insert(Overlaps2.begin(), Overlaps2.end()); + } + } +} + +void CodeGenRegBank::computeDerivedInfo() { + computeComposites(); +} + +/// getRegisterClassForRegister - Find the register class that contains the +/// specified physical register. If the register is not in a register class, +/// return null. If the register is in multiple classes, and the classes have a +/// superset-subset relationship and the same set of types, return the +/// superclass. Otherwise return null. +const CodeGenRegisterClass* +CodeGenRegBank::getRegClassForRegister(Record *R) { + const CodeGenRegister *Reg = getReg(R); + const std::vector<CodeGenRegisterClass> &RCs = getRegClasses(); + const CodeGenRegisterClass *FoundRC = 0; + for (unsigned i = 0, e = RCs.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = RCs[i]; + if (!RC.contains(Reg)) + continue; + + // If this is the first class that contains the register, + // make a note of it and go on to the next class. + if (!FoundRC) { + FoundRC = &RC; + continue; + } + + // If a register's classes have different types, return null. + if (RC.getValueTypes() != FoundRC->getValueTypes()) + return 0; + + // Check to see if the previously found class that contains + // the register is a subclass of the current class. If so, + // prefer the superclass. + if (RC.hasSubClass(FoundRC)) { + FoundRC = &RC; + continue; + } + + // Check to see if the previously found class that contains + // the register is a superclass of the current class. If so, + // prefer the superclass. + if (FoundRC->hasSubClass(&RC)) + continue; + + // Multiple classes, and neither is a superclass of the other. + // Return null. + return 0; + } + return FoundRC; +} diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index f6d6af8..55f0b9b 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -15,34 +15,85 @@ #ifndef CODEGEN_REGISTERS_H #define CODEGEN_REGISTERS_H +#include "Record.h" +#include "SetTheory.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" +#include <cstdlib> +#include <map> #include <string> -#include <vector> #include <set> -#include <cstdlib> +#include <vector> namespace llvm { - class Record; + class CodeGenRegBank; /// CodeGenRegister - Represents a register definition. struct CodeGenRegister { Record *TheDef; - const std::string &getName() const; - unsigned DeclaredSpillSize, DeclaredSpillAlignment; unsigned EnumValue; - CodeGenRegister(Record *R); + unsigned CostPerUse; + + // Map SubRegIndex -> Register. + typedef std::map<Record*, CodeGenRegister*, LessRecord> SubRegMap; + + CodeGenRegister(Record *R, unsigned Enum); + + const std::string &getName() const; + + // Get a map of sub-registers computed lazily. + // This includes unique entries for all sub-sub-registers. + const SubRegMap &getSubRegs(CodeGenRegBank&); + + const SubRegMap &getSubRegs() const { + assert(SubRegsComplete && "Must precompute sub-registers"); + return SubRegs; + } + + // Add sub-registers to OSet following a pre-order defined by the .td file. + void addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const; + + // List of super-registers in topological order, small to large. + typedef std::vector<CodeGenRegister*> SuperRegList; + + // Get the list of super-registers. + // This is only valid after computeDerivedInfo has visited all registers. + const SuperRegList &getSuperRegs() const { + assert(SubRegsComplete && "Must precompute sub-registers"); + return SuperRegs; + } + + // Order CodeGenRegister pointers by EnumValue. + struct Less { + bool operator()(const CodeGenRegister *A, + const CodeGenRegister *B) const { + return A->EnumValue < B->EnumValue; + } + }; + + // Canonically ordered set. + typedef std::set<const CodeGenRegister*, Less> Set; + + private: + bool SubRegsComplete; + SubRegMap SubRegs; + SuperRegList SuperRegs; }; - struct CodeGenRegisterClass { + class CodeGenRegisterClass { + CodeGenRegister::Set Members; + const std::vector<Record*> *Elements; + public: Record *TheDef; std::string Namespace; - std::vector<Record*> Elements; std::vector<MVT::SimpleValueType> VTs; unsigned SpillSize; unsigned SpillAlignment; int CopyCost; + bool Allocatable; // Map SubRegIndex -> RegisterClass DenseMap<Record*,Record*> SubRegClasses; std::string MethodProtos, MethodBodies; @@ -58,13 +109,10 @@ namespace llvm { abort(); } - bool containsRegister(Record *R) const { - for (unsigned i = 0, e = Elements.size(); i != e; ++i) - if (Elements[i] == R) return true; - return false; - } + // Return true if this this class contains the register. + bool contains(const CodeGenRegister*) const; - // Returns true if RC is a strict subclass. + // Returns true if RC is a subclass. // RC is a sub-class of this class if it is a valid replacement for any // instruction operand where a register of this classis required. It must // satisfy these conditions: @@ -73,29 +121,86 @@ namespace llvm { // 2. The RC spill size must not be smaller than our spill size. // 3. RC spill alignment must be compatible with ours. // - bool hasSubClass(const CodeGenRegisterClass *RC) const { + bool hasSubClass(const CodeGenRegisterClass *RC) const; - if (RC->Elements.size() > Elements.size() || - (SpillAlignment && RC->SpillAlignment % SpillAlignment) || - SpillSize > RC->SpillSize) - return false; + // Returns an ordered list of class members. + // The order of registers is the same as in the .td file. + ArrayRef<Record*> getOrder() const { + return *Elements; + } - std::set<Record*> RegSet; - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - Record *Reg = Elements[i]; - RegSet.insert(Reg); - } + CodeGenRegisterClass(CodeGenRegBank&, Record *R); + }; - for (unsigned i = 0, e = RC->Elements.size(); i != e; ++i) { - Record *Reg = RC->Elements[i]; - if (!RegSet.count(Reg)) - return false; - } + // CodeGenRegBank - Represent a target's registers and the relations between + // them. + class CodeGenRegBank { + RecordKeeper &Records; + SetTheory Sets; + + std::vector<Record*> SubRegIndices; + unsigned NumNamedIndices; + std::vector<CodeGenRegister> Registers; + DenseMap<Record*, CodeGenRegister*> Def2Reg; + + std::vector<CodeGenRegisterClass> RegClasses; + DenseMap<Record*, CodeGenRegisterClass*> Def2RC; + + // Composite SubRegIndex instances. + // Map (SubRegIndex, SubRegIndex) -> SubRegIndex. + typedef DenseMap<std::pair<Record*, Record*>, Record*> CompositeMap; + CompositeMap Composite; + + // Populate the Composite map from sub-register relationships. + void computeComposites(); + + public: + CodeGenRegBank(RecordKeeper&); + + SetTheory &getSets() { return Sets; } - return true; + // Sub-register indices. The first NumNamedIndices are defined by the user + // in the .td files. The rest are synthesized such that all sub-registers + // have a unique name. + const std::vector<Record*> &getSubRegIndices() { return SubRegIndices; } + unsigned getNumNamedIndices() { return NumNamedIndices; } + + // Map a SubRegIndex Record to its enum value. + unsigned getSubRegIndexNo(Record *idx); + + // Find or create a sub-register index representing the A+B composition. + Record *getCompositeSubRegIndex(Record *A, Record *B, bool create = false); + + const std::vector<CodeGenRegister> &getRegisters() { return Registers; } + + // Find a register from its Record def. + CodeGenRegister *getReg(Record*); + + const std::vector<CodeGenRegisterClass> &getRegClasses() { + return RegClasses; } - CodeGenRegisterClass(Record *R); + // Find a register class from its def. + CodeGenRegisterClass *getRegClass(Record*); + + /// getRegisterClassForRegister - Find the register class that contains the + /// specified physical register. If the register is not in a register + /// class, return null. If the register is in multiple classes, and the + /// classes have a superset-subset relationship and the same set of types, + /// return the superclass. Otherwise return null. + const CodeGenRegisterClass* getRegClassForRegister(Record *R); + + // Computed derived records such as missing sub-register indices. + void computeDerivedInfo(); + + // Compute full overlap sets for every register. These sets include the + // rarely used aliases that are neither sub nor super-registers. + // + // Map[R1].count(R2) is reflexive and symmetric, but not transitive. + // + // If R1 is a sub-register of R2, Map[R1] is a subset of Map[R2]. + void computeOverlaps(std::map<const CodeGenRegister*, + CodeGenRegister::Set> &Map); }; } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index cc09c8d..4ce8022 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -90,6 +90,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; + case MVT::untyped: return "MVT::untyped"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } } @@ -98,17 +99,18 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { /// namespace qualifier if the record contains one. /// std::string llvm::getQualifiedName(const Record *R) { - std::string Namespace = R->getValueAsString("Namespace"); + std::string Namespace; + if (R->getValue("Namespace")) + Namespace = R->getValueAsString("Namespace"); if (Namespace.empty()) return R->getName(); return Namespace + "::" + R->getName(); } - - /// getTarget - Return the current instance of the Target class. /// -CodeGenTarget::CodeGenTarget(RecordKeeper &records) : Records(records) { +CodeGenTarget::CodeGenTarget(RecordKeeper &records) + : Records(records), RegBank(0) { std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) throw std::string("ERROR: No 'Target' subclasses defined!"); @@ -156,47 +158,16 @@ Record *CodeGenTarget::getAsmWriter() const { return LI[AsmWriterNum]; } -void CodeGenTarget::ReadRegisters() const { - std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); - if (Regs.empty()) - throw std::string("No 'Register' subclasses defined!"); - std::sort(Regs.begin(), Regs.end(), LessRecord()); - - Registers.reserve(Regs.size()); - Registers.assign(Regs.begin(), Regs.end()); - // Assign the enumeration values. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i].EnumValue = i + 1; -} - -CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) { - DeclaredSpillSize = R->getValueAsInt("SpillSize"); - DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment"); -} - -const std::string &CodeGenRegister::getName() const { - return TheDef->getName(); -} - -void CodeGenTarget::ReadSubRegIndices() const { - SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); - std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord()); -} - -void CodeGenTarget::ReadRegisterClasses() const { - std::vector<Record*> RegClasses = - Records.getAllDerivedDefinitions("RegisterClass"); - if (RegClasses.empty()) - throw std::string("No 'RegisterClass' subclasses defined!"); - - RegisterClasses.reserve(RegClasses.size()); - RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); +CodeGenRegBank &CodeGenTarget::getRegBank() const { + if (!RegBank) + RegBank = new CodeGenRegBank(Records); + return *RegBank; } /// getRegisterByName - If there is a register with the specific AsmName, /// return it. const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { - const std::vector<CodeGenRegister> &Regs = getRegisters(); + const std::vector<CodeGenRegister> &Regs = getRegBank().getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = Regs[i]; if (Reg.TheDef->getValueAsString("AsmName") == Name) @@ -208,15 +179,14 @@ const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { std::vector<MVT::SimpleValueType> CodeGenTarget:: getRegisterVTs(Record *R) const { + const CodeGenRegister *Reg = getRegBank().getReg(R); std::vector<MVT::SimpleValueType> Result; const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { - if (R == RC.Elements[ei]) { - const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); - Result.insert(Result.end(), InVTs.begin(), InVTs.end()); - } + const CodeGenRegisterClass &RC = RCs[i]; + if (RC.contains(Reg)) { + const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); + Result.insert(Result.end(), InVTs.begin(), InVTs.end()); } } @@ -227,70 +197,6 @@ getRegisterVTs(Record *R) const { } -CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { - // Rename anonymous register classes. - if (R->getName().size() > 9 && R->getName()[9] == '.') { - static unsigned AnonCounter = 0; - R->setName("AnonRegClass_"+utostr(AnonCounter++)); - } - - std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); - for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { - Record *Type = TypeList[i]; - if (!Type->isSubClassOf("ValueType")) - throw "RegTypes list member '" + Type->getName() + - "' does not derive from the ValueType class!"; - VTs.push_back(getValueType(Type)); - } - assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); - - std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList"); - for (unsigned i = 0, e = RegList.size(); i != e; ++i) { - Record *Reg = RegList[i]; - if (!Reg->isSubClassOf("Register")) - throw "Register Class member '" + Reg->getName() + - "' does not derive from the Register class!"; - Elements.push_back(Reg); - } - - // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. - ListInit *SRC = R->getValueAsListInit("SubRegClasses"); - for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { - DagInit *DAG = dynamic_cast<DagInit*>(*i); - if (!DAG) throw "SubRegClasses must contain DAGs"; - DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator()); - Record *RCRec; - if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass")) - throw "Operator '" + DAG->getOperator()->getAsString() + - "' in SubRegClasses is not a RegisterClass"; - // Iterate over args, all SubRegIndex instances. - for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end(); - ai != ae; ++ai) { - DefInit *Idx = dynamic_cast<DefInit*>(*ai); - Record *IdxRec; - if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex")) - throw "Argument '" + (*ai)->getAsString() + - "' in SubRegClasses is not a SubRegIndex"; - if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second) - throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice"; - } - } - - // Allow targets to override the size in bits of the RegisterClass. - unsigned Size = R->getValueAsInt("Size"); - - Namespace = R->getValueAsString("Namespace"); - SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); - SpillAlignment = R->getValueAsInt("Alignment"); - CopyCost = R->getValueAsInt("CopyCost"); - MethodBodies = R->getValueAsCode("MethodBodies"); - MethodProtos = R->getValueAsCode("MethodProtos"); -} - -const std::string &CodeGenRegisterClass::getName() const { - return TheDef->getName(); -} - void CodeGenTarget::ReadLegalValueTypes() const { const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) @@ -454,6 +360,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { ModRef = ReadWriteMem; isOverloaded = false; isCommutative = false; + canThrow = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") @@ -576,10 +483,15 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { ModRef = ReadWriteArgMem; else if (Property->getName() == "Commutative") isCommutative = true; + else if (Property->getName() == "Throws") + canThrow = true; else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); } else assert(0 && "Unknown property!"); } + + // Sort the argument attributes for later benefit. + std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); } diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 4e04154..2516515 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -65,13 +65,8 @@ class CodeGenTarget { Record *TargetRec; mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; - mutable std::vector<CodeGenRegister> Registers; - mutable std::vector<Record*> SubRegIndices; - mutable std::vector<CodeGenRegisterClass> RegisterClasses; + mutable CodeGenRegBank *RegBank; mutable std::vector<MVT::SimpleValueType> LegalValueTypes; - void ReadRegisters() const; - void ReadSubRegIndices() const; - void ReadRegisterClasses() const; void ReadInstructions() const; void ReadLegalValueTypes() const; @@ -98,95 +93,23 @@ public: /// Record *getAsmWriter() const; + /// getRegBank - Return the register bank description. + CodeGenRegBank &getRegBank() const; + const std::vector<CodeGenRegister> &getRegisters() const { - if (Registers.empty()) ReadRegisters(); - return Registers; + return getRegBank().getRegisters(); } /// getRegisterByName - If there is a register with the specific AsmName, /// return it. const CodeGenRegister *getRegisterByName(StringRef Name) const; - const std::vector<Record*> &getSubRegIndices() const { - if (SubRegIndices.empty()) ReadSubRegIndices(); - return SubRegIndices; - } - - // Map a SubRegIndex Record to its number. - unsigned getSubRegIndexNo(Record *idx) const { - if (SubRegIndices.empty()) ReadSubRegIndices(); - std::vector<Record*>::const_iterator i = - std::find(SubRegIndices.begin(), SubRegIndices.end(), idx); - assert(i != SubRegIndices.end() && "Not a SubRegIndex"); - return (i - SubRegIndices.begin()) + 1; - } - const std::vector<CodeGenRegisterClass> &getRegisterClasses() const { - if (RegisterClasses.empty()) ReadRegisterClasses(); - return RegisterClasses; + return getRegBank().getRegClasses(); } const CodeGenRegisterClass &getRegisterClass(Record *R) const { - const std::vector<CodeGenRegisterClass> &RC = getRegisterClasses(); - for (unsigned i = 0, e = RC.size(); i != e; ++i) - if (RC[i].TheDef == R) - return RC[i]; - assert(0 && "Didn't find the register class"); - abort(); - } - - /// getRegisterClassForRegister - Find the register class that contains the - /// specified physical register. If the register is not in a register - /// class, return null. If the register is in multiple classes, and the - /// classes have a superset-subset relationship and the same set of - /// types, return the superclass. Otherwise return null. - const CodeGenRegisterClass *getRegisterClassForRegister(Record *R) const { - const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); - const CodeGenRegisterClass *FoundRC = 0; - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { - if (R != RC.Elements[ei]) - continue; - - // If a register's classes have different types, return null. - if (FoundRC && RC.getValueTypes() != FoundRC->getValueTypes()) - return 0; - - // If this is the first class that contains the register, - // make a note of it and go on to the next class. - if (!FoundRC) { - FoundRC = &RC; - break; - } - - std::vector<Record *> Elements(RC.Elements); - std::vector<Record *> FoundElements(FoundRC->Elements); - std::sort(Elements.begin(), Elements.end()); - std::sort(FoundElements.begin(), FoundElements.end()); - - // Check to see if the previously found class that contains - // the register is a subclass of the current class. If so, - // prefer the superclass. - if (std::includes(Elements.begin(), Elements.end(), - FoundElements.begin(), FoundElements.end())) { - FoundRC = &RC; - break; - } - - // Check to see if the previously found class that contains - // the register is a superclass of the current class. If so, - // prefer the superclass. - if (std::includes(FoundElements.begin(), FoundElements.end(), - Elements.begin(), Elements.end())) - break; - - // Multiple classes, and neither is a superclass of the other. - // Return null. - return 0; - } - } - return FoundRC; + return *getRegBank().getRegClass(R); } /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 2117e65..35ab550 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -16,7 +16,6 @@ #include "TableGenBackend.h" #include "CodeGenDAGPatterns.h" -#include <set> namespace llvm { diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index 2afa2b9..b12e101 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -83,6 +83,15 @@ ScopeMatcher::~ScopeMatcher() { } +CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred) + : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {} + +TreePredicateFn CheckPredicateMatcher::getPredicate() const { + return TreePredicateFn(Pred); +} + + + // printImpl methods. void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -129,7 +138,7 @@ printImpl(raw_ostream &OS, unsigned indent) const { } void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "CheckPredicate " << PredName << '\n'; + OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n'; } void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -263,7 +272,7 @@ unsigned CheckPatternPredicateMatcher::getHashImpl() const { } unsigned CheckPredicateMatcher::getHashImpl() const { - return HashString(PredName); + return HashString(getPredicate().getFnName()); } unsigned CheckOpcodeMatcher::getHashImpl() const { @@ -301,7 +310,6 @@ bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const { Opcode.getEnumName(); } - bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const { const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m); return M->OpcodeName == OpcodeName && M->VTs == VTs && diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 8ffe412..dcb8da7 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -25,6 +25,8 @@ namespace llvm { class ComplexPattern; class Record; class SDNodeInfo; + class TreePredicateFn; + class TreePattern; Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, const CodeGenDAGPatterns &CGP); @@ -419,12 +421,11 @@ private: /// CheckPredicateMatcher - This checks the target-specific predicate to /// see if the node is acceptable. class CheckPredicateMatcher : public Matcher { - StringRef PredName; + TreePattern *Pred; public: - CheckPredicateMatcher(StringRef predname) - : Matcher(CheckPredicate), PredName(predname) {} + CheckPredicateMatcher(const TreePredicateFn &pred); - StringRef getPredicateName() const { return PredName; } + TreePredicateFn getPredicate() const; static inline bool classof(const Matcher *N) { return N->getKind() == CheckPredicate; @@ -436,7 +437,7 @@ public: private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { - return cast<CheckPredicateMatcher>(M)->PredName == PredName; + return cast<CheckPredicateMatcher>(M)->Pred == Pred; } virtual unsigned getHashImpl() const; }; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 0b69af4..acb0135 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -33,8 +33,12 @@ OmitComments("omit-comments", cl::desc("Do not generate comments"), namespace { class MatcherTableEmitter { const CodeGenDAGPatterns &CGP; - StringMap<unsigned> NodePredicateMap, PatternPredicateMap; - std::vector<std::string> NodePredicates, PatternPredicates; + + DenseMap<TreePattern *, unsigned> NodePredicateMap; + std::vector<TreePredicateFn> NodePredicates; + + StringMap<unsigned> PatternPredicateMap; + std::vector<std::string> PatternPredicates; DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap; std::vector<const ComplexPattern*> ComplexPatterns; @@ -57,14 +61,15 @@ private: unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, formatted_raw_ostream &OS); - unsigned getNodePredicate(StringRef PredName) { - unsigned &Entry = NodePredicateMap[PredName]; + unsigned getNodePredicate(TreePredicateFn Pred) { + unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()]; if (Entry == 0) { - NodePredicates.push_back(PredName.str()); + NodePredicates.push_back(Pred); Entry = NodePredicates.size(); } return Entry-1; } + unsigned getPatternPredicate(StringRef PredName) { unsigned &Entry = PatternPredicateMap[PredName]; if (Entry == 0) { @@ -73,7 +78,6 @@ private: } return Entry-1; } - unsigned getComplexPat(const ComplexPattern &P) { unsigned &Entry = ComplexPatternMap[&P]; if (Entry == 0) { @@ -239,7 +243,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 2; case Matcher::CheckPatternPredicate: { - StringRef Pred = cast<CheckPatternPredicateMatcher>(N)->getPredicate(); + StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate(); OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ','; if (!OmitComments) OS.PadToColumn(CommentIndent) << "// " << Pred; @@ -247,10 +251,10 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 2; } case Matcher::CheckPredicate: { - StringRef Pred = cast<CheckPredicateMatcher>(N)->getPredicateName(); + TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate(); OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ','; if (!OmitComments) - OS.PadToColumn(CommentIndent) << "// " << Pred; + OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName(); OS << '\n'; return 2; } @@ -617,25 +621,13 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { OS << " switch (PredNo) {\n"; OS << " default: assert(0 && \"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { - // FIXME: Storing this by name is horrible. - TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))]; - assert(P && "Unknown name?"); - // Emit the predicate code corresponding to this pattern. - std::string Code = P->getRecord()->getValueAsCode("Predicate"); - assert(!Code.empty() && "No code in this predicate"); - OS << " case " << i << ": { // " << NodePredicates[i] << '\n'; - std::string ClassName; - if (P->getOnlyTree()->isLeaf()) - ClassName = "SDNode"; - else - ClassName = - CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName(); - if (ClassName == "SDNode") - OS << " SDNode *N = Node;\n"; - else - OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n"; - OS << Code << "\n }\n"; + TreePredicateFn PredFn = NodePredicates[i]; + + assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); + OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n'; + + OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; } OS << " }\n"; OS << "}\n\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 393ac69..a8736fa 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -25,12 +25,12 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget &T) { bool FoundRC = false; MVT::SimpleValueType VT = MVT::Other; + const CodeGenRegister *Reg = T.getRegBank().getReg(R); const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses(); - std::vector<Record*>::const_iterator Element; for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RCs[rc]; - if (!std::count(RC.Elements.begin(), RC.Elements.end(), R)) + if (!RC.contains(Reg)) continue; if (!FoundRC) { @@ -646,6 +646,35 @@ GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { return InstPatNode; } +static bool +mayInstNodeLoadOrStore(const TreePatternNode *N, + const CodeGenDAGPatterns &CGP) { + Record *Op = N->getOperator(); + const CodeGenTarget &CGT = CGP.getTargetInfo(); + CodeGenInstruction &II = CGT.getInstruction(Op); + return II.mayLoad || II.mayStore; +} + +static unsigned +numNodesThatMayLoadOrStore(const TreePatternNode *N, + const CodeGenDAGPatterns &CGP) { + if (N->isLeaf()) + return 0; + + Record *OpRec = N->getOperator(); + if (!OpRec->isSubClassOf("Instruction")) + return 0; + + unsigned Count = 0; + if (mayInstNodeLoadOrStore(N, CGP)) + ++Count; + + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + Count += numNodesThatMayLoadOrStore(N->getChild(i), CGP); + + return Count; +} + void MatcherGen:: EmitResultInstructionAsOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &OutputOps) { @@ -772,21 +801,26 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); - // If this is the root node and any of the nodes matched nodes in the input - // pattern have MemRefs in them, have the interpreter collect them and plop - // them onto this node. - // - // FIXME3: This is actively incorrect for result patterns where the root of - // the pattern is not the memory reference and is also incorrect when the - // result pattern has multiple memory-referencing instructions. For example, - // in the X86 backend, this pattern causes the memrefs to get attached to the - // CVTSS2SDrr instead of the MOVSSrm: + // If this is the root node and multiple matched nodes in the input pattern + // have MemRefs in them, have the interpreter collect them and plop them onto + // this node. If there is just one node with MemRefs, leave them on that node + // even if it is not the root. // - // def : Pat<(extloadf32 addr:$src), - // (CVTSS2SDrr (MOVSSrm addr:$src))>; - // - bool NodeHasMemRefs = - isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); + // FIXME3: This is actively incorrect for result patterns with multiple + // memory-referencing instructions. + bool PatternHasMemOperands = + Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); + + bool NodeHasMemRefs = false; + if (PatternHasMemOperands) { + unsigned NumNodesThatLoadOrStore = + numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP); + bool NodeIsUniqueLoadOrStore = mayInstNodeLoadOrStore(N, CGP) && + NumNodesThatLoadOrStore == 1; + NodeHasMemRefs = + NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) || + NumNodesThatLoadOrStore != 1)); + } assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) && "Node has no result"); diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 3169ea1..f996422 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -18,7 +18,6 @@ #include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include <vector> using namespace llvm; /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 8415482..daf9617 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -24,7 +24,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include <map> #include <string> #include <vector> @@ -597,6 +596,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("t_adrlabel"); IMM("t2adrlabel"); IMM("shift_imm"); + IMM("ssat_imm"); IMM("neon_vcvt_imm32"); IMM("shr_imm8"); IMM("shr_imm16"); @@ -636,6 +636,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I MISC("addrmode7", "kOperandTypeARMAddrMode7"); // R MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index f01de1d..6c2a767 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -19,9 +19,10 @@ #include "FastISelEmitter.h" #include "Record.h" -#include "llvm/Support/Debug.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; namespace { @@ -35,36 +36,150 @@ struct InstructionMemo { std::string SubRegNo; std::vector<std::string>* PhysRegs; }; + +/// ImmPredicateSet - This uniques predicates (represented as a string) and +/// gives them unique (small) integer ID's that start at 0. +class ImmPredicateSet { + DenseMap<TreePattern *, unsigned> ImmIDs; + std::vector<TreePredicateFn> PredsByName; +public: + + unsigned getIDFor(TreePredicateFn Pred) { + unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()]; + if (Entry == 0) { + PredsByName.push_back(Pred); + Entry = PredsByName.size(); + } + return Entry-1; + } + + const TreePredicateFn &getPredicate(unsigned i) { + assert(i < PredsByName.size()); + return PredsByName[i]; + } + + typedef std::vector<TreePredicateFn>::const_iterator iterator; + iterator begin() const { return PredsByName.begin(); } + iterator end() const { return PredsByName.end(); } + +}; /// OperandsSignature - This class holds a description of a list of operand /// types. It has utility methods for emitting text based on the operands. /// struct OperandsSignature { - std::vector<std::string> Operands; + class OpKind { + enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 }; + char Repr; + public: + + OpKind() : Repr(OK_Invalid) {} + + bool operator<(OpKind RHS) const { return Repr < RHS.Repr; } + bool operator==(OpKind RHS) const { return Repr == RHS.Repr; } + + static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; } + static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; } + static OpKind getImm(unsigned V) { + assert((unsigned)OK_Imm+V < 128 && + "Too many integer predicates for the 'Repr' char"); + OpKind K; K.Repr = OK_Imm+V; return K; + } + + bool isReg() const { return Repr == OK_Reg; } + bool isFP() const { return Repr == OK_FP; } + bool isImm() const { return Repr >= OK_Imm; } + + unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; } + + void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes) const { + if (isReg()) + OS << 'r'; + else if (isFP()) + OS << 'f'; + else { + OS << 'i'; + if (!StripImmCodes) + if (unsigned Code = getImmCode()) + OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName(); + } + } + }; + + + SmallVector<OpKind, 3> Operands; bool operator<(const OperandsSignature &O) const { return Operands < O.Operands; } + bool operator==(const OperandsSignature &O) const { + return Operands == O.Operands; + } bool empty() const { return Operands.empty(); } + bool hasAnyImmediateCodes() const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (Operands[i].isImm() && Operands[i].getImmCode() != 0) + return true; + return false; + } + + /// getWithoutImmCodes - Return a copy of this with any immediate codes forced + /// to zero. + OperandsSignature getWithoutImmCodes() const { + OperandsSignature Result; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!Operands[i].isImm()) + Result.Operands.push_back(Operands[i]); + else + Result.Operands.push_back(OpKind::getImm(0)); + return Result; + } + + void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) { + bool EmittedAnything = false; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (!Operands[i].isImm()) continue; + + unsigned Code = Operands[i].getImmCode(); + if (Code == 0) continue; + + if (EmittedAnything) + OS << " &&\n "; + + TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1); + + // Emit the type check. + OS << "VT == " + << getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0)) + << " && "; + + + OS << PredFn.getFnName() << "(imm" << i <<')'; + EmittedAnything = true; + } + } + /// initialize - Examine the given pattern and initialize the contents /// of the Operands array accordingly. Return true if all the operands /// are supported, false otherwise. /// - bool initialize(TreePatternNode *InstPatNode, - const CodeGenTarget &Target, - MVT::SimpleValueType VT) { - - if (!InstPatNode->isLeaf()) { - if (InstPatNode->getOperator()->getName() == "imm") { - Operands.push_back("i"); - return true; - } - if (InstPatNode->getOperator()->getName() == "fpimm") { - Operands.push_back("f"); - return true; - } + bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target, + MVT::SimpleValueType VT, + ImmPredicateSet &ImmediatePredicates) { + if (InstPatNode->isLeaf()) + return false; + + if (InstPatNode->getOperator()->getName() == "imm") { + Operands.push_back(OpKind::getImm(0)); + return true; + } + + if (InstPatNode->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); + return true; } const CodeGenRegisterClass *DstRC = 0; @@ -72,40 +187,70 @@ struct OperandsSignature { for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); + // Handle imm operands specially. + if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") { + unsigned PredNo = 0; + if (!Op->getPredicateFns().empty()) { + TreePredicateFn PredFn = Op->getPredicateFns()[0]; + // If there is more than one predicate weighing in on this operand + // then we don't handle it. This doesn't typically happen for + // immediates anyway. + if (Op->getPredicateFns().size() > 1 || + !PredFn.isImmediatePattern()) + return false; + // Ignore any instruction with 'FastIselShouldIgnore', these are + // not needed and just bloat the fast instruction selector. For + // example, X86 doesn't need to generate code to match ADD16ri8 since + // ADD16ri will do just fine. + Record *Rec = PredFn.getOrigPatFragRecord()->getRecord(); + if (Rec->getValueAsBit("FastIselShouldIgnore")) + return false; + + PredNo = ImmediatePredicates.getIDFor(PredFn)+1; + } + + // Handle unmatched immediate sizes here. + //if (Op->getType(0) != VT) + // return false; + + Operands.push_back(OpKind::getImm(PredNo)); + continue; + } + + // For now, filter out any operand with a predicate. // For now, filter out any operand with multiple values. - if (!Op->getPredicateFns().empty() || - Op->getNumTypes() != 1) - return false; - - assert(Op->hasTypeSet(0) && "Type infererence not done?"); - // For now, all the operands must have the same type. - if (Op->getType(0) != VT) + if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1) return false; if (!Op->isLeaf()) { - if (Op->getOperator()->getName() == "imm") { - Operands.push_back("i"); - continue; - } - if (Op->getOperator()->getName() == "fpimm") { - Operands.push_back("f"); + if (Op->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); continue; } // For now, ignore other non-leaf nodes. return false; } + + assert(Op->hasTypeSet(0) && "Type infererence not done?"); + + // For now, all the operands must have the same type (if they aren't + // immediates). Note that this causes us to reject variable sized shifts + // on X86. + if (Op->getType(0) != VT) + return false; + DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); if (!OpDI) return false; Record *OpLeafRec = OpDI->getDef(); + // For now, the only other thing we accept is register operands. - const CodeGenRegisterClass *RC = 0; if (OpLeafRec->isSubClassOf("RegisterClass")) RC = &Target.getRegisterClass(OpLeafRec); else if (OpLeafRec->isSubClassOf("Register")) - RC = Target.getRegisterClassForRegister(OpLeafRec); + RC = Target.getRegBank().getRegClassForRegister(OpLeafRec); else return false; @@ -120,22 +265,21 @@ struct OperandsSignature { return false; } else DstRC = RC; - Operands.push_back("r"); + Operands.push_back(OpKind::getReg()); } return true; } void PrintParameters(raw_ostream &OS) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "unsigned Op" << i << ", bool Op" << i << "IsKill"; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "uint64_t imm" << i; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "ConstantFP *f" << i; } else { - assert("Unknown operand kind!"); - abort(); + llvm_unreachable("Unknown operand kind!"); } if (i + 1 != e) OS << ", "; @@ -143,7 +287,7 @@ struct OperandsSignature { } void PrintArguments(raw_ostream &OS, - const std::vector<std::string>& PR) const { + const std::vector<std::string> &PR) const { assert(PR.size() == Operands.size()); bool PrintedArg = false; for (unsigned i = 0, e = Operands.size(); i != e; ++i) { @@ -153,33 +297,31 @@ struct OperandsSignature { if (PrintedArg) OS << ", "; - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "Op" << i << ", Op" << i << "IsKill"; PrintedArg = true; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "imm" << i; PrintedArg = true; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "f" << i; PrintedArg = true; } else { - assert("Unknown operand kind!"); - abort(); + llvm_unreachable("Unknown operand kind!"); } } } void PrintArguments(raw_ostream &OS) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "Op" << i << ", Op" << i << "IsKill"; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "imm" << i; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "f" << i; } else { - assert("Unknown operand kind!"); - abort(); + llvm_unreachable("Unknown operand kind!"); } if (i + 1 != e) OS << ", "; @@ -187,8 +329,9 @@ struct OperandsSignature { } - void PrintManglingSuffix(raw_ostream &OS, - const std::vector<std::string>& PR) const { + void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR, + ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { if (PR[i] != "") // Implicit physical register operand. e.g. Instruction::Mul expect to @@ -197,14 +340,14 @@ struct OperandsSignature { // like a binary instruction except for the very inner FastEmitInst_* // call. continue; - OS << Operands[i]; + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); } } - void PrintManglingSuffix(raw_ostream &OS) const { - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - OS << Operands[i]; - } + void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); } }; @@ -218,13 +361,17 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + std::map<OperandsSignature, std::vector<OperandsSignature> > + SignaturesWithConstantForms; + std::string InstNS; - + ImmPredicateSet ImmediatePredicates; public: explicit FastISelMap(std::string InstNS); - void CollectPatterns(CodeGenDAGPatterns &CGP); - void PrintFunctionDefinitions(raw_ostream &OS); + void collectPatterns(CodeGenDAGPatterns &CGP); + void printImmediatePredicates(raw_ostream &OS); + void printFunctionDefinitions(raw_ostream &OS); }; } @@ -244,7 +391,34 @@ FastISelMap::FastISelMap(std::string instns) : InstNS(instns) { } -void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { +static std::string PhyRegForNode(TreePatternNode *Op, + const CodeGenTarget &Target) { + std::string PhysReg; + + if (!Op->isLeaf()) + return PhysReg; + + DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); + Record *OpLeafRec = OpDI->getDef(); + if (!OpLeafRec->isSubClassOf("Register")) + return PhysReg; + + PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \ + "Namespace")->getValue())->getValue(); + PhysReg += "::"; + + std::vector<CodeGenRegister> Regs = Target.getRegisters(); + for (unsigned i = 0; i < Regs.size(); ++i) { + if (Regs[i].TheDef == OpLeafRec) { + PhysReg += Regs[i].getName(); + break; + } + } + + return PhysReg; +} + +void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { const CodeGenTarget &Target = CGP.getTargetInfo(); // Determine the target's namespace name. @@ -264,7 +438,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { if (!Op->isSubClassOf("Instruction")) continue; CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); - if (II.Operands.size() == 0) + if (II.Operands.empty()) continue; // For now, ignore multi-instruction patterns. @@ -322,54 +496,45 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { VT = InstPatNode->getChild(0)->getType(0); } - // For now, filter out instructions which just set a register to - // an Operand or an immediate, like MOV32ri. - if (InstPatOp->isSubClassOf("Operand")) - continue; - // For now, filter out any instructions with predicates. if (!InstPatNode->getPredicateFns().empty()) continue; // Check all the operands. OperandsSignature Operands; - if (!Operands.initialize(InstPatNode, Target, VT)) + if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates)) continue; std::vector<std::string>* PhysRegInputs = new std::vector<std::string>(); - if (!InstPatNode->isLeaf() && - (InstPatNode->getOperator()->getName() == "imm" || - InstPatNode->getOperator()->getName() == "fpimmm")) + if (InstPatNode->getOperator()->getName() == "imm" || + InstPatNode->getOperator()->getName() == "fpimmm") PhysRegInputs->push_back(""); - else if (!InstPatNode->isLeaf()) { + else { + // Compute the PhysRegs used by the given pattern, and check that + // the mapping from the src to dst patterns is simple. + bool FoundNonSimplePattern = false; + unsigned DstIndex = 0; for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { - TreePatternNode *Op = InstPatNode->getChild(i); - if (!Op->isLeaf()) { - PhysRegInputs->push_back(""); - continue; - } - - DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); - Record *OpLeafRec = OpDI->getDef(); - std::string PhysReg; - if (OpLeafRec->isSubClassOf("Register")) { - PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \ - "Namespace")->getValue())->getValue(); - PhysReg += "::"; - - std::vector<CodeGenRegister> Regs = Target.getRegisters(); - for (unsigned i = 0; i < Regs.size(); ++i) { - if (Regs[i].TheDef == OpLeafRec) { - PhysReg += Regs[i].getName(); - break; - } + std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target); + if (PhysReg.empty()) { + if (DstIndex >= Dst->getNumChildren() || + Dst->getChild(DstIndex)->getName() != + InstPatNode->getChild(i)->getName()) { + FoundNonSimplePattern = true; + break; } + ++DstIndex; } PhysRegInputs->push_back(PhysReg); } - } else - PhysRegInputs->push_back(""); + + if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren()) + FoundNonSimplePattern = true; + + if (FoundNonSimplePattern) + continue; + } // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -381,15 +546,39 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { SubRegNo, PhysRegInputs }; - if (SimplePatterns[Operands][OpcodeName][VT][RetVT] - .count(PredicateCheck)) - throw TGError(Pattern.getSrcRecord()->getLoc(), "Duplicate record!"); + + if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + throw TGError(Pattern.getSrcRecord()->getLoc(), + "Duplicate record in FastISel table!"); SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = 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 + // associate them with the stripped predicate version. + if (Operands.hasAnyImmediateCodes()) { + SignaturesWithConstantForms[Operands.getWithoutImmCodes()] + .push_back(Operands); + } } } -void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { +void FastISelMap::printImmediatePredicates(raw_ostream &OS) { + if (ImmediatePredicates.begin() == ImmediatePredicates.end()) + return; + + OS << "\n// FastEmit Immediate Predicate functions.\n"; + for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(), + E = ImmediatePredicates.end(); I != E; ++I) { + OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n"; + OS << I->getImmediatePredicateCode() << "\n}\n"; + } + + OS << "\n\n"; +} + + +void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(), OE = SimplePatterns.end(); OI != OE; ++OI) { @@ -420,7 +609,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "("; Operands.PrintParameters(OS); OS << ") {\n"; @@ -451,7 +640,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " return FastEmitInst_"; if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); OS << "(" << InstNS << Memo.Name << ", "; OS << InstNS << Memo.RC->getName() << "RegisterClass"; if (!Operands.empty()) @@ -460,9 +650,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << ");\n"; } else { OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; + OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; } if (HasPred) @@ -480,7 +668,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -492,7 +680,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " case " << getName(RetVT) << ": return FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "("; Operands.PrintArguments(OS); OS << ");\n"; @@ -504,7 +692,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -544,7 +732,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " return FastEmitInst_"; if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); OS << "(" << InstNS << Memo.Name << ", "; OS << InstNS << Memo.RC->getName() << "RegisterClass"; if (!Operands.empty()) @@ -572,7 +761,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { // Emit one function for the opcode that demultiplexes based on the type. OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -585,7 +774,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { std::string TypeName = getName(VT); OS << " case " << TypeName << ": return FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; if (!Operands.empty()) OS << ", "; @@ -604,12 +793,44 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. OS << "unsigned FastEmit_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); OS << ") {\n"; + + // If there are any forms of this signature available that operand on + // constrained forms of the immediate (e.g. 32-bit sext immediate in a + // 64-bit operand), check them first. + + std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI + = SignaturesWithConstantForms.find(Operands); + if (MI != SignaturesWithConstantForms.end()) { + // Unique any duplicates out of the list. + std::sort(MI->second.begin(), MI->second.end()); + MI->second.erase(std::unique(MI->second.begin(), MI->second.end()), + MI->second.end()); + + // Check each in order it was seen. It would be nice to have a good + // relative ordering between them, but we're not going for optimality + // here. + for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { + OS << " if ("; + MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); + OS << ")\n if (unsigned Reg = FastEmit_"; + MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(VT, RetVT, Opcode"; + if (!MI->second[i].empty()) + OS << ", "; + MI->second[i].PrintArguments(OS); + OS << "))\n return Reg;\n\n"; + } + + // Done with this, remove it. + SignaturesWithConstantForms.erase(MI); + } + OS << " switch (Opcode) {\n"; for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end(); I != E; ++I) { @@ -617,7 +838,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " case " << Opcode << ": return FastEmit_" << getLegalCName(Opcode) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; if (!Operands.empty()) OS << ", "; @@ -629,6 +850,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "}\n"; OS << "\n"; } + + // TODO: SignaturesWithConstantForms should be empty here. } void FastISelEmitter::run(raw_ostream &OS) { @@ -642,12 +865,12 @@ void FastISelEmitter::run(raw_ostream &OS) { Target.getName() + " target", OS); FastISelMap F(InstNS); - F.CollectPatterns(CGP); - F.PrintFunctionDefinitions(OS); + F.collectPatterns(CGP); + F.printImmediatePredicates(OS); + F.printFunctionDefinitions(OS); } FastISelEmitter::FastISelEmitter(RecordKeeper &R) - : Records(R), - CGP(R) { + : Records(R), CGP(R) { } diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index bbcecab..9312fe8 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -438,7 +438,7 @@ void Filter::recurse() { for (bitIndex = 0; bitIndex < NumBits; bitIndex++) BitValueArray[StartBit + bitIndex] = BIT_UNSET; - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( (unsigned)-1, @@ -471,7 +471,7 @@ void Filter::recurse() { BitValueArray[StartBit + bitIndex] = BIT_FALSE; } - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // category of instructions. FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( mapIterator->first, @@ -611,7 +611,8 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) { o << '\n'; o.indent(Indentation) << - "static bool decodeInstruction(MCInst &MI, field_t insn) {\n"; + "static bool decodeInstruction(MCInst &MI, field_t insn, " + "uint64_t Address, const void *Decoder) {\n"; o.indent(Indentation) << " unsigned tmp = 0;\n"; ++Indentation; ++Indentation; @@ -795,7 +796,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->FieldBase == ~0U && I->FieldLength == ~0U) { - o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, insn, Address, Decoder);\n"; break; } @@ -803,7 +805,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, << " tmp = fieldFromInstruction(insn, " << I->FieldBase << ", " << I->FieldLength << ");\n"; if (I->Decoder != "") { - o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, tmp, Address, Decoder);\n"; } else { o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; @@ -846,7 +849,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->FieldBase == ~0U && I->FieldLength == ~0U) { - o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, insn, Address, Decoder);\n"; break; } @@ -854,7 +858,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, << " tmp = fieldFromInstruction(insn, " << I->FieldBase << ", " << I->FieldLength << ");\n"; if (I->Decoder != "") { - o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, tmp, Address, Decoder);\n"; } else { o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 67cce0e..fc544ee 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -166,13 +166,13 @@ void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs, for (unsigned i = 0, e = RCs.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RCs[i]; - unsigned NumRegs = RC.Elements.size(); - if (NumRegs > NumDefs) + ArrayRef<Record*> Order = RC.getOrder(); + if (Order.size() > NumDefs) continue; // Can't possibly clobber this RC. bool Clobber = true; - for (unsigned j = 0; j < NumRegs; ++j) { - Record *Reg = RC.Elements[j]; + for (unsigned j = 0; j < Order.size(); ++j) { + Record *Reg = Order[j]; if (!DefSet.count(Reg)) { Clobber = false; break; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 08f6728..39eb3bd 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -465,6 +465,46 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; } +namespace { + enum ModRefKind { + MRK_none, + MRK_readonly, + MRK_readnone + }; + + ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { + switch (intrinsic.ModRef) { + case CodeGenIntrinsic::NoMem: + return MRK_readnone; + case CodeGenIntrinsic::ReadArgMem: + case CodeGenIntrinsic::ReadMem: + return MRK_readonly; + case CodeGenIntrinsic::ReadWriteArgMem: + case CodeGenIntrinsic::ReadWriteMem: + return MRK_none; + } + assert(0 && "bad mod-ref kind"); + return MRK_none; + } + + struct AttributeComparator { + bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { + // Sort throwing intrinsics after non-throwing intrinsics. + if (L->canThrow != R->canThrow) + return R->canThrow; + + // Try to order by readonly/readnone attribute. + ModRefKind LK = getModRefKind(*L); + ModRefKind RK = getModRefKind(*R); + if (LK != RK) return (LK > RK); + + // Order by argument attributes. + // This is reliable because each side is already sorted internally. + return (L->ArgumentAttributes < R->ArgumentAttributes); + } + }; +} + /// EmitAttributes - This emits the Intrinsic::getAttributes method. void IntrinsicEmitter:: EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { @@ -472,84 +512,96 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; if (TargetOnly) OS << "static AttrListPtr getAttributes(" << TargetPrefix - << "Intrinsic::ID id) {"; + << "Intrinsic::ID id) {\n"; else - OS << "AttrListPtr Intrinsic::getAttributes(ID id) {"; - OS << " // No intrinsic can throw exceptions.\n"; - OS << " Attributes Attr = Attribute::NoUnwind;\n"; - OS << " switch (id) {\n"; - OS << " default: break;\n"; - unsigned MaxArgAttrs = 0; + OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n"; + + // Compute the maximum number of attribute arguments. + std::vector<const CodeGenIntrinsic*> sortedIntrinsics(Ints.size()); + unsigned maxArgAttrs = 0; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - MaxArgAttrs = - std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size())); - switch (Ints[i].ModRef) { - default: break; - case CodeGenIntrinsic::NoMem: - OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName - << ":\n"; - break; - } + const CodeGenIntrinsic &intrinsic = Ints[i]; + sortedIntrinsics[i] = &intrinsic; + maxArgAttrs = + std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size())); } - OS << " Attr |= Attribute::ReadNone; // These do not access memory.\n"; - OS << " break;\n"; - for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - switch (Ints[i].ModRef) { - default: break; - case CodeGenIntrinsic::ReadArgMem: - case CodeGenIntrinsic::ReadMem: - OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName - << ":\n"; - break; - } - } - OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n"; - OS << " break;\n"; - OS << " }\n"; - OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n"; + + // Emit an array of AttributeWithIndex. Most intrinsics will have + // at least one entry, for the function itself (index ~1), which is + // usually nounwind. + OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; OS << " unsigned NumAttrs = 0;\n"; OS << " switch (id) {\n"; - OS << " default: break;\n"; - - // Add argument attributes for any intrinsics that have them. - for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - if (Ints[i].ArgumentAttributes.empty()) continue; - - OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName - << ":\n"; + OS << " default: break;\n"; + + AttributeComparator precedes; - std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs = - Ints[i].ArgumentAttributes; - // Sort by argument index. - std::sort(ArgAttrs.begin(), ArgAttrs.end()); + std::stable_sort(sortedIntrinsics.begin(), sortedIntrinsics.end(), precedes); + + for (unsigned i = 0, e = sortedIntrinsics.size(); i != e; ++i) { + const CodeGenIntrinsic &intrinsic = *sortedIntrinsics[i]; + OS << " case " << TargetPrefix << "Intrinsic::" + << intrinsic.EnumName << ":\n"; + + // Fill out the case if this is the last case for this range of + // intrinsics. + if (i + 1 != e && !precedes(&intrinsic, sortedIntrinsics[i + 1])) + continue; - unsigned NumArgsWithAttrs = 0; + // Keep track of the number of attributes we're writing out. + unsigned numAttrs = 0; - while (!ArgAttrs.empty()) { - unsigned ArgNo = ArgAttrs[0].first; + // The argument attributes are alreadys sorted by argument index. + for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) { + unsigned argNo = intrinsic.ArgumentAttributes[ai].first; - OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get(" - << ArgNo+1 << ", 0"; + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(" + << argNo+1 << ", "; - while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) { - switch (ArgAttrs[0].second) { - default: assert(0 && "Unknown arg attribute"); + bool moreThanOne = false; + + do { + if (moreThanOne) OS << '|'; + + switch (intrinsic.ArgumentAttributes[ai].second) { case CodeGenIntrinsic::NoCapture: - OS << "|Attribute::NoCapture"; + OS << "Attribute::NoCapture"; break; } - ArgAttrs.erase(ArgAttrs.begin()); + + ++ai; + moreThanOne = true; + } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); + + OS << ");\n"; + } + + ModRefKind modRef = getModRefKind(intrinsic); + + if (!intrinsic.canThrow || modRef) { + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; + if (!intrinsic.canThrow) { + OS << "Attribute::NoUnwind"; + if (modRef) OS << '|'; + } + switch (modRef) { + case MRK_none: break; + case MRK_readonly: OS << "Attribute::ReadOnly"; break; + case MRK_readnone: OS << "Attribute::ReadNone"; break; } OS << ");\n"; } - - OS << " NumAttrs = " << NumArgsWithAttrs << ";\n"; - OS << " break;\n"; + + if (numAttrs) { + OS << " NumAttrs = " << numAttrs << ";\n"; + OS << " break;\n"; + } else { + OS << " return AttrListPtr();\n"; + } } OS << " }\n"; - OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n"; - OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n"; + OS << " return AttrListPtr::get(AWI, NumAttrs);\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index c40a39d..090faf5 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -74,6 +74,25 @@ int InitPtrToInt(const Init* ptr) { return val.getValue(); } +bool InitPtrToBool(const Init* ptr) { + bool ret = false; + const DefInit& val = dynamic_cast<const DefInit&>(*ptr); + const std::string& str = val.getAsString(); + + if (str == "true") { + ret = true; + } + else if (str == "false") { + ret = false; + } + else { + throw "Incorrect boolean value: '" + str + + "': must be either 'true' or 'false'"; + } + + return ret; +} + const std::string& InitPtrToString(const Init* ptr) { const StringInit& val = dynamic_cast<const StringInit&>(*ptr); return val.getValue(); @@ -95,13 +114,7 @@ const std::string GetOperatorName(const DagInit& D) { /// CheckBooleanConstant - Check that the provided value is a boolean constant. void CheckBooleanConstant(const Init* I) { - const DefInit& val = dynamic_cast<const DefInit&>(*I); - const std::string& str = val.getAsString(); - - if (str != "true" && str != "false") { - throw "Incorrect boolean value: '" + str + - "': must be either 'true' or 'false'"; - } + InitPtrToBool(I); } // CheckNumberOfArguments - Ensure that the number of args in d is @@ -935,8 +948,22 @@ private: } void onJoin (const DagInit& d) { - CheckNumberOfArguments(d, 0); - toolDesc_.setJoin(); + bool isReallyJoin = false; + + if (d.getNumArgs() == 0) { + isReallyJoin = true; + } + else { + Init* I = d.getArg(0); + isReallyJoin = InitPtrToBool(I); + } + + // Is this *really* a join tool? We allow (join false) for generating two + // tool descriptions from a single generic one. + // TOFIX: come up with a cleaner solution. + if (isReallyJoin) { + toolDesc_.setJoin(); + } } void onOutLanguage (const DagInit& d) { @@ -3028,6 +3055,8 @@ void CheckDriverData(DriverData& Data) { FilterNotInGraph(Data.Edges, Data.ToolDescs); // Typecheck the compilation graph. + // TODO: use a genuine graph representation instead of a vector and check for + // multiple edges. TypecheckGraph(Data.Edges, Data.ToolDescs); // Check that there are no options without side effects (specified diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index d522c79..23fdbde 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -462,9 +462,34 @@ static std::string MangleName(const std::string &name, StringRef typestr, return s; } +/// UseMacro - Examine the prototype string to determine if the intrinsic +/// should be defined as a preprocessor macro instead of an inline function. +static bool UseMacro(const std::string &proto) { + // If this builtin takes an immediate argument, we need to #define it rather + // than use a standard declaration, so that SemaChecking can range check + // the immediate passed by the user. + if (proto.find('i') != std::string::npos) + return true; + + // Pointer arguments need to use macros to avoid hiding aligned attributes + // from the pointer type. + if (proto.find('p') != std::string::npos || + proto.find('c') != std::string::npos) + return true; + + return false; +} + +/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is +/// defined as a macro should be accessed directly instead of being first +/// assigned to a local temporary. +static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) { + return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c'); +} + // Generate the string "(argtype a, argtype b, ...)" static std::string GenArgs(const std::string &proto, StringRef typestr) { - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); char arg = 'a'; std::string s; @@ -472,10 +497,10 @@ static std::string GenArgs(const std::string &proto, StringRef typestr) { for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { if (define) { - // Immediate macro arguments are used directly instead of being assigned + // Some macro arguments are used directly instead of being assigned // to local temporaries; prepend an underscore prefix to make their // names consistent with the local temporaries. - if (proto[i] == 'i') + if (MacroArgUsedDirectly(proto, i)) s += "__"; } else { s += TypeString(proto[i], typestr) + " __"; @@ -494,11 +519,28 @@ static std::string GenArgs(const std::string &proto, StringRef typestr) { static std::string GenMacroLocals(const std::string &proto, StringRef typestr) { char arg = 'a'; std::string s; + bool generatedLocal = false; for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { // Do not create a temporary for an immediate argument. // That would defeat the whole point of using a macro! - if (proto[i] == 'i') continue; + if (proto[i] == 'i') + continue; + generatedLocal = true; + + // For other (non-immediate) arguments that are used directly, a local + // temporary is still needed to get the correct type checking, even though + // that temporary is not used for anything. + if (MacroArgUsedDirectly(proto, i)) { + s += TypeString(proto[i], typestr) + " __"; + s.push_back(arg); + s += "_ = (__"; + s.push_back(arg); + s += "); (void)__"; + s.push_back(arg); + s += "_; "; + continue; + } s += TypeString(proto[i], typestr) + " __"; s.push_back(arg); @@ -507,7 +549,8 @@ static std::string GenMacroLocals(const std::string &proto, StringRef typestr) { s += "); "; } - s += "\\\n "; + if (generatedLocal) + s += "\\\n "; return s; } @@ -568,11 +611,7 @@ static std::string GenOpString(OpKind op, const std::string &proto, StringRef typestr) { bool quad; unsigned nElts = GetNumElements(typestr, quad); - - // If this builtin takes an immediate argument, we need to #define it rather - // than use a standard declaration, so that SemaChecking can range check - // the immediate passed by the user. - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); std::string ts = TypeString(proto[0], typestr); std::string s; @@ -858,10 +897,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, // sret-like argument. bool sret = (proto[0] >= '2' && proto[0] <= '4'); - // If this builtin takes an immediate argument, we need to #define it rather - // than use a standard declaration, so that SemaChecking can range check - // the immediate passed by the user. - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); // Check if the prototype has a scalar operand with the type of the vector // elements. If not, bitcasting the args will take care of arg checking. @@ -999,7 +1035,7 @@ static std::string GenIntrinsic(const std::string &name, StringRef outTypeStr, StringRef inTypeStr, OpKind kind, ClassKind classKind) { assert(!proto.empty() && ""); - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); std::string s; // static always inline + return type @@ -1362,9 +1398,14 @@ void NeonEmitter::runHeader(raw_ostream &OS) { for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { std::string namestr, shiftstr, rangestr; - // Builtins which are overloaded by type will need to have their upper - // bound computed at Sema time based on the type constant. - if (Proto.find('s') == std::string::npos) { + if (R->getValueAsBit("isVCVT_N")) { + // VCVT between floating- and fixed-point values takes an immediate + // in the range 1 to 32. + ck = ClassB; + rangestr = "l = 1; u = 31"; // upper bound = l + u + } else if (Proto.find('s') == std::string::npos) { + // Builtins which are overloaded by type will need to have their upper + // bound computed at Sema time based on the type constant. ck = ClassB; if (R->getValueAsBit("isShift")) { shiftstr = ", true"; diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 6892912..431026c 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -35,7 +35,7 @@ static int CompareOptionRecords(const void *Av, const void *Bv) { const Record *A = *(Record**) Av; const Record *B = *(Record**) Bv; - // Sentinel options preceed all others and are only ordered by precedence. + // Sentinel options precede all others and are only ordered by precedence. bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); if (ASent != BSent) diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index abbbafe..8ac8cd9 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -68,14 +68,9 @@ Init *BitsRecTy::convertValue(BitInit *UI) { /// canFitInBitfield - Return true if the number of bits is large enough to hold /// the integer value. static bool canFitInBitfield(int64_t Value, unsigned NumBits) { - if (Value >= 0) { - if (Value & ~((1LL << NumBits) - 1)) - return false; - } else if ((Value >> NumBits) != -1 || (Value & (1LL << (NumBits-1))) == 0) { - return false; - } - - return true; + // For example, with NumBits == 4, we permit Values from [-7 .. 15]. + return (NumBits >= sizeof(Value) * 8) || + (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1); } /// convertValue from Int initializer to bits type: Split the integer up into the @@ -583,9 +578,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (Record *D = (CurRec->getRecords()).getDef(Name)) return new DefInit(D); - errs() << "Variable not defined: '" + Name + "'\n"; - assert(0 && "Variable not found"); - return 0; + throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); } } break; @@ -813,15 +806,13 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, OpInit *RHSo = dynamic_cast<OpInit*>(RHS); if (!RHSo) { - errs() << "!foreach requires an operator\n"; - assert(0 && "No operator for !foreach"); + throw TGError(CurRec->getLoc(), "!foreach requires an operator\n"); } TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS); if (!LHSt) { - errs() << "!foreach requires typed variable\n"; - assert(0 && "No typed variable for !foreach"); + throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n"); } if ((MHSd && DagType) || (MHSl && ListType)) { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index f3a5df2..522b719 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -707,7 +707,7 @@ class CodeInit : public Init { public: explicit CodeInit(const std::string &V) : Value(V) {} - const std::string getValue() const { return Value; } + const std::string &getValue() const { return Value; } virtual Init *convertInitializerTo(RecTy *Ty) { return Ty->convertValue(this); diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index b3a9dea..9ffb66a 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -19,6 +19,7 @@ #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Format.h" #include <algorithm> #include <set> using namespace llvm; @@ -26,6 +27,7 @@ using namespace llvm; // runEnums - Print out enum values for all of the registers. void RegisterInfoEmitter::runEnums(raw_ostream &OS) { CodeGenTarget Target(Records); + CodeGenRegBank &Bank = Target.getRegBank(); const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace"); @@ -47,16 +49,16 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { if (!Namespace.empty()) OS << "}\n"; - const std::vector<Record*> SubRegIndices = Target.getSubRegIndices(); + const std::vector<Record*> &SubRegIndices = Bank.getSubRegIndices(); if (!SubRegIndices.empty()) { OS << "\n// Subregister indices\n"; Namespace = SubRegIndices[0]->getValueAsString("Namespace"); if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; - OS << " NUM_TARGET_SUBREGS = " << SubRegIndices.size()+1 << "\n"; + OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) OS << "}\n"; @@ -80,6 +82,8 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" + << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " + << "unsigned Flavour) const;\n" << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n" << " virtual bool needsStackRealignment(const MachineFunction &) const\n" << " { return false; }\n" @@ -122,256 +126,52 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "} // End llvm namespace \n"; } -static void addSuperReg(Record *R, Record *S, - std::map<Record*, std::set<Record*>, LessRecord> &SubRegs, - std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs, - std::map<Record*, std::set<Record*>, LessRecord> &Aliases) { - if (R == S) { - errs() << "Error: recursive sub-register relationship between" - << " register " << getQualifiedName(R) - << " and its sub-registers?\n"; - abort(); - } - if (!SuperRegs[R].insert(S).second) - return; - SubRegs[S].insert(R); - Aliases[R].insert(S); - Aliases[S].insert(R); - if (SuperRegs.count(S)) - for (std::set<Record*>::iterator I = SuperRegs[S].begin(), - E = SuperRegs[S].end(); I != E; ++I) - addSuperReg(R, *I, SubRegs, SuperRegs, Aliases); -} - -static void addSubSuperReg(Record *R, Record *S, - std::map<Record*, std::set<Record*>, LessRecord> &SubRegs, - std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs, - std::map<Record*, std::set<Record*>, LessRecord> &Aliases) { - if (R == S) { - errs() << "Error: recursive sub-register relationship between" - << " register " << getQualifiedName(R) - << " and its sub-registers?\n"; - abort(); - } - - if (!SubRegs[R].insert(S).second) - return; - addSuperReg(S, R, SubRegs, SuperRegs, Aliases); - Aliases[R].insert(S); - Aliases[S].insert(R); - if (SubRegs.count(S)) - for (std::set<Record*>::iterator I = SubRegs[S].begin(), - E = SubRegs[S].end(); I != E; ++I) - addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases); -} - -struct RegisterMaps { - // Map SubRegIndex -> Register - typedef std::map<Record*, Record*, LessRecord> SubRegMap; - // Map Register -> SubRegMap - typedef std::map<Record*, SubRegMap> SubRegMaps; - - SubRegMaps SubReg; - SubRegMap &inferSubRegIndices(Record *Reg); - - // Composite SubRegIndex instances. - // Map (SubRegIndex,SubRegIndex) -> SubRegIndex - typedef DenseMap<std::pair<Record*,Record*>,Record*> CompositeMap; - CompositeMap Composite; - - // Compute SubRegIndex compositions after inferSubRegIndices has run on all - // registers. - void computeComposites(); -}; - -// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion. -RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) { - SubRegMap &SRM = SubReg[Reg]; - if (!SRM.empty()) - return SRM; - std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs"); - std::vector<Record*> Indices = Reg->getValueAsListOfDefs("SubRegIndices"); - if (SubRegs.size() != Indices.size()) - throw "Register " + Reg->getName() + " SubRegIndices doesn't match SubRegs"; - - // First insert the direct subregs and make sure they are fully indexed. - for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) { - if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second) - throw "SubRegIndex " + Indices[i]->getName() - + " appears twice in Register " + Reg->getName(); - inferSubRegIndices(SubRegs[i]); - } - - // Keep track of inherited subregs and how they can be reached. - // Register -> (SubRegIndex, SubRegIndex) - typedef std::map<Record*, std::pair<Record*,Record*>, LessRecord> OrphanMap; - OrphanMap Orphans; - - // Clone inherited subregs. Here the order is important - earlier subregs take - // precedence. - for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) { - SubRegMap &M = SubReg[SubRegs[i]]; - for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si) - if (!SRM.insert(*si).second) - Orphans[si->second] = std::make_pair(Indices[i], si->first); - } - - // Finally process the composites. - ListInit *Comps = Reg->getValueAsListInit("CompositeIndices"); - for (unsigned i = 0, e = Comps->size(); i != e; ++i) { - DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); - if (!Pat) - throw "Invalid dag '" + Comps->getElement(i)->getAsString() - + "' in CompositeIndices"; - DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); - if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) - throw "Invalid SubClassIndex in " + Pat->getAsString(); - - // Resolve list of subreg indices into R2. - Record *R2 = Reg; - for (DagInit::const_arg_iterator di = Pat->arg_begin(), - de = Pat->arg_end(); di != de; ++di) { - DefInit *IdxInit = dynamic_cast<DefInit*>(*di); - if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) - throw "Invalid SubClassIndex in " + Pat->getAsString(); - SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef()); - if (ni == SubReg[R2].end()) - throw "Composite " + Pat->getAsString() + " refers to bad index in " - + R2->getName(); - R2 = ni->second; - } - - // Insert composite index. Allow overriding inherited indices etc. - SRM[BaseIdxInit->getDef()] = R2; - - // R2 is now directly addressable, no longer an orphan. - Orphans.erase(R2); - } - - // Now, Orphans contains the inherited subregisters without a direct index. - if (!Orphans.empty()) { - errs() << "Error: Register " << getQualifiedName(Reg) - << " inherited subregisters without an index:\n"; - for (OrphanMap::iterator i = Orphans.begin(), e = Orphans.end(); i != e; - ++i) { - errs() << " " << getQualifiedName(i->first) - << " = " << i->second.first->getName() - << ", " << i->second.second->getName() << "\n"; - } - abort(); - } - return SRM; -} - -void RegisterMaps::computeComposites() { - for (SubRegMaps::const_iterator sri = SubReg.begin(), sre = SubReg.end(); - sri != sre; ++sri) { - Record *Reg1 = sri->first; - const SubRegMap &SRM1 = sri->second; - for (SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); - i1 != e1; ++i1) { - Record *Idx1 = i1->first; - Record *Reg2 = i1->second; - // Ignore identity compositions. - if (Reg1 == Reg2) - continue; - // If Reg2 has no subregs, Idx1 doesn't compose. - if (!SubReg.count(Reg2)) - continue; - const SubRegMap &SRM2 = SubReg[Reg2]; - // Try composing Idx1 with another SubRegIndex. - for (SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end(); - i2 != e2; ++i2) { - std::pair<Record*,Record*> IdxPair(Idx1, i2->first); - Record *Reg3 = i2->second; - // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. - for (SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end(); - i1d != e1d; ++i1d) { - // Ignore identity compositions. - if (Reg2 == Reg3) - continue; - if (i1d->second == Reg3) { - std::pair<CompositeMap::iterator,bool> Ins = - Composite.insert(std::make_pair(IdxPair, i1d->first)); - // Conflicting composition? - if (!Ins.second && Ins.first->second != i1d->first) { - errs() << "Error: SubRegIndex " << getQualifiedName(Idx1) - << " and " << getQualifiedName(IdxPair.second) - << " compose ambiguously as " - << getQualifiedName(Ins.first->second) << " or " - << getQualifiedName(i1d->first) << "\n"; - abort(); - } - } - } - } - } - } - - // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid - // compositions, so remove any mappings of that form. - for (CompositeMap::iterator i = Composite.begin(), e = Composite.end(); - i != e;) { - CompositeMap::iterator j = i; - ++i; - if (j->first.second == j->second) - Composite.erase(j); - } -} - -class RegisterSorter { -private: - std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs; - -public: - RegisterSorter(std::map<Record*, std::set<Record*>, LessRecord> &RS) - : RegisterSubRegs(RS) {} - - bool operator()(Record *RegA, Record *RegB) { - // B is sub-register of A. - return RegisterSubRegs.count(RegA) && RegisterSubRegs[RegA].count(RegB); - } -}; +typedef std::pair<unsigned, unsigned> UUPair; +typedef std::vector<UUPair> UUVector; +// // RegisterInfoEmitter::run - Main register file description emitter. // void RegisterInfoEmitter::run(raw_ostream &OS) { CodeGenTarget Target(Records); + CodeGenRegBank &RegBank = Target.getRegBank(); + RegBank.computeDerivedInfo(); + std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps; + RegBank.computeOverlaps(Overlaps); + EmitSourceFileHeader("Register Information Source Fragment", OS); OS << "namespace llvm {\n\n"; - // Start out by emitting each of the register classes... to do this, we build - // a set of registers which belong to a register class, this is to ensure that - // each register is only in a single register class. - // + // Start out by emitting each of the register classes. const std::vector<CodeGenRegisterClass> &RegisterClasses = Target.getRegisterClasses(); + // Collect all registers belonging to any allocatable class. + std::set<Record*> AllocatableRegs; + // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; - // RegClassesBelongedTo - Keep track of which register classes each reg - // belongs to. - std::multimap<Record*, const CodeGenRegisterClass*> RegClassesBelongedTo; - // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; + ArrayRef<Record*> Order = RC.getOrder(); + + // Collect allocatable registers. + if (RC.Allocatable) + AllocatableRegs.insert(Order.begin(), Order.end()); // Give the register class a legal C name if it's anonymous. - std::string Name = RC.TheDef->getName(); + std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " static const unsigned " << Name << "[] = {\n "; - for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) { - Record *Reg = RC.Elements[i]; + for (unsigned i = 0, e = Order.size(); i != e; ++i) { + Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; - - // Keep track of which regclasses this register is in. - RegClassesBelongedTo.insert(std::make_pair(Reg, &RC)); } OS << "\n };\n\n"; } @@ -381,7 +181,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; // Give the register class a legal C name if it's anonymous. - std::string Name = RC.TheDef->getName() + "VTs"; + std::string Name = RC.getName() + "VTs"; // Emit the register list now. OS << " // " << Name @@ -406,7 +206,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { std::map<unsigned, std::set<unsigned> > SuperRegClassMap; OS << "\n"; - unsigned NumSubRegIndices = Target.getSubRegIndices().size(); + unsigned NumSubRegIndices = RegBank.getSubRegIndices().size(); if (NumSubRegIndices) { // Emit the sub-register classes for each RegisterClass @@ -417,7 +217,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { i = RC.SubRegClasses.begin(), e = RC.SubRegClasses.end(); i != e; ++i) { // Build SRC array. - unsigned idx = Target.getSubRegIndexNo(i->first); + unsigned idx = RegBank.getSubRegIndexNo(i->first); SRC.at(idx-1) = i->second; // Find the register class number of i->second for SuperRegClassMap. @@ -567,7 +367,9 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " - << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size() + << RC.Allocatable << ", " + << RC.getName() << ", " << RC.getName() << " + " + << RC.getOrder().size() << ") {}\n"; } @@ -581,267 +383,58 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << "RegClass,\n"; OS << " };\n"; - // Emit register sub-registers / super-registers, aliases... - std::map<Record*, std::set<Record*>, LessRecord> RegisterSubRegs; - std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs; - std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases; typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; - const std::vector<CodeGenRegister> &Regs = Target.getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *R = Regs[i].TheDef; - std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("Aliases"); - // Add information that R aliases all of the elements in the list... and - // that everything in the list aliases R. - for (unsigned j = 0, e = LI.size(); j != e; ++j) { - Record *Reg = LI[j]; - if (RegisterAliases[R].count(Reg)) - errs() << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg) - << " specified multiple times!\n"; - RegisterAliases[R].insert(Reg); - - if (RegisterAliases[Reg].count(R)) - errs() << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg) - << " specified multiple times!\n"; - RegisterAliases[Reg].insert(R); - } - } - - // Process sub-register sets. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *R = Regs[i].TheDef; - std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("SubRegs"); - // Process sub-register set and add aliases information. - for (unsigned j = 0, e = LI.size(); j != e; ++j) { - Record *SubReg = LI[j]; - if (RegisterSubRegs[R].count(SubReg)) - errs() << "Warning: register " << getQualifiedName(SubReg) - << " specified as a sub-register of " << getQualifiedName(R) - << " multiple times!\n"; - addSubSuperReg(R, SubReg, RegisterSubRegs, RegisterSuperRegs, - RegisterAliases); - } - } - - // Print the SubregHashTable, a simple quadratically probed - // hash table for determining if a register is a subregister - // of another register. - unsigned NumSubRegs = 0; - std::map<Record*, unsigned> RegNo; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegNo[Regs[i].TheDef] = i; - NumSubRegs += RegisterSubRegs[Regs[i].TheDef].size(); - } - - unsigned SubregHashTableSize = 2 * NextPowerOf2(2 * NumSubRegs); - unsigned* SubregHashTable = new unsigned[2 * SubregHashTableSize]; - std::fill(SubregHashTable, SubregHashTable + 2 * SubregHashTableSize, ~0U); - - unsigned hashMisses = 0; - - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record* R = Regs[i].TheDef; - for (std::set<Record*>::iterator I = RegisterSubRegs[R].begin(), - E = RegisterSubRegs[R].end(); I != E; ++I) { - Record* RJ = *I; - // We have to increase the indices of both registers by one when - // computing the hash because, in the generated code, there - // will be an extra empty slot at register 0. - size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (SubregHashTableSize-1); - unsigned ProbeAmt = 2; - while (SubregHashTable[index*2] != ~0U && - SubregHashTable[index*2+1] != ~0U) { - index = (index + ProbeAmt) & (SubregHashTableSize-1); - ProbeAmt += 2; - - hashMisses++; - } - - SubregHashTable[index*2] = i; - SubregHashTable[index*2+1] = RegNo[RJ]; - } - } - - OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - - if (SubregHashTableSize) { - std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - - OS << " const unsigned SubregHashTable[] = { "; - for (unsigned i = 0; i < SubregHashTableSize - 1; ++i) { - if (i != 0) - // Insert spaces for nice formatting. - OS << " "; - - if (SubregHashTable[2*i] != ~0U) { - OS << getQualifiedName(Regs[SubregHashTable[2*i]].TheDef) << ", " - << getQualifiedName(Regs[SubregHashTable[2*i+1]].TheDef) << ", \n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; - } - } - - unsigned Idx = SubregHashTableSize*2-2; - if (SubregHashTable[Idx] != ~0U) { - OS << " " - << getQualifiedName(Regs[SubregHashTable[Idx]].TheDef) << ", " - << getQualifiedName(Regs[SubregHashTable[Idx+1]].TheDef) << " };\n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; - } - - OS << " const unsigned SubregHashTableSize = " - << SubregHashTableSize << ";\n"; - } else { - OS << " const unsigned SubregHashTable[] = { ~0U, ~0U };\n" - << " const unsigned SubregHashTableSize = 1;\n"; - } - - delete [] SubregHashTable; - - - // Print the AliasHashTable, a simple quadratically probed - // hash table for determining if a register aliases another register. - unsigned NumAliases = 0; - RegNo.clear(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegNo[Regs[i].TheDef] = i; - NumAliases += RegisterAliases[Regs[i].TheDef].size(); - } - - unsigned AliasesHashTableSize = 2 * NextPowerOf2(2 * NumAliases); - unsigned* AliasesHashTable = new unsigned[2 * AliasesHashTableSize]; - std::fill(AliasesHashTable, AliasesHashTable + 2 * AliasesHashTableSize, ~0U); - - hashMisses = 0; - - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record* R = Regs[i].TheDef; - for (std::set<Record*>::iterator I = RegisterAliases[R].begin(), - E = RegisterAliases[R].end(); I != E; ++I) { - Record* RJ = *I; - // We have to increase the indices of both registers by one when - // computing the hash because, in the generated code, there - // will be an extra empty slot at register 0. - size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (AliasesHashTableSize-1); - unsigned ProbeAmt = 2; - while (AliasesHashTable[index*2] != ~0U && - AliasesHashTable[index*2+1] != ~0U) { - index = (index + ProbeAmt) & (AliasesHashTableSize-1); - ProbeAmt += 2; - - hashMisses++; - } - - AliasesHashTable[index*2] = i; - AliasesHashTable[index*2+1] = RegNo[RJ]; - } - } - - OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - - if (AliasesHashTableSize) { - std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - - OS << " const unsigned AliasesHashTable[] = { "; - for (unsigned i = 0; i < AliasesHashTableSize - 1; ++i) { - if (i != 0) - // Insert spaces for nice formatting. - OS << " "; - - if (AliasesHashTable[2*i] != ~0U) { - OS << getQualifiedName(Regs[AliasesHashTable[2*i]].TheDef) << ", " - << getQualifiedName(Regs[AliasesHashTable[2*i+1]].TheDef) << ", \n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; - } - } - - unsigned Idx = AliasesHashTableSize*2-2; - if (AliasesHashTable[Idx] != ~0U) { - OS << " " - << getQualifiedName(Regs[AliasesHashTable[Idx]].TheDef) << ", " - << getQualifiedName(Regs[AliasesHashTable[Idx+1]].TheDef) << " };\n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; - } - - OS << " const unsigned AliasesHashTableSize = " - << AliasesHashTableSize << ";\n"; - } else { - OS << " const unsigned AliasesHashTable[] = { ~0U, ~0U };\n" - << " const unsigned AliasesHashTableSize = 1;\n"; - } - - delete [] AliasesHashTable; - - if (!RegisterAliases.empty()) - OS << "\n\n // Register Overlap Lists...\n"; - // Emit an overlap list for all registers. - for (std::map<Record*, std::set<Record*>, LessRecord >::iterator - I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) { - OS << " const unsigned " << I->first->getName() << "_Overlaps[] = { " - << getQualifiedName(I->first) << ", "; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - OS << getQualifiedName(*ASI) << ", "; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = &Regs[i]; + const CodeGenRegister::Set &O = Overlaps[Reg]; + // Move Reg to the front so TRI::getAliasSet can share the list. + OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " + << getQualifiedName(Reg->TheDef) << ", "; + for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); + I != E; ++I) + if (*I != Reg) + OS << getQualifiedName((*I)->TheDef) << ", "; OS << "0 };\n"; } - if (!RegisterSubRegs.empty()) - OS << "\n\n // Register Sub-registers Sets...\n"; - // Emit the empty sub-registers list OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n"; // Loop over all of the registers which have sub-registers, emitting the // sub-registers list to memory. - for (std::map<Record*, std::set<Record*>, LessRecord>::iterator - I = RegisterSubRegs.begin(), E = RegisterSubRegs.end(); I != E; ++I) { - if (I->second.empty()) + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = Regs[i]; + if (Reg.getSubRegs().empty()) continue; - OS << " const unsigned " << I->first->getName() << "_SubRegsSet[] = { "; - std::vector<Record*> SubRegsVector; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - SubRegsVector.push_back(*ASI); - RegisterSorter RS(RegisterSubRegs); - std::stable_sort(SubRegsVector.begin(), SubRegsVector.end(), RS); - for (unsigned i = 0, e = SubRegsVector.size(); i != e; ++i) - OS << getQualifiedName(SubRegsVector[i]) << ", "; + // getSubRegs() orders by SubRegIndex. We want a topological order. + SetVector<CodeGenRegister*> SR; + Reg.addSubRegsPreOrder(SR); + OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; OS << "0 };\n"; } - if (!RegisterSuperRegs.empty()) - OS << "\n\n // Register Super-registers Sets...\n"; - // Emit the empty super-registers list OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; // Loop over all of the registers which have super-registers, emitting the // super-registers list to memory. - for (std::map<Record*, std::set<Record*>, LessRecord >::iterator - I = RegisterSuperRegs.begin(), E = RegisterSuperRegs.end(); I != E; ++I) { - if (I->second.empty()) + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = Regs[i]; + const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); + if (SR.empty()) continue; - OS << " const unsigned " << I->first->getName() << "_SuperRegsSet[] = { "; - - std::vector<Record*> SuperRegsVector; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - SuperRegsVector.push_back(*ASI); - RegisterSorter RS(RegisterSubRegs); - std::stable_sort(SuperRegsVector.begin(), SuperRegsVector.end(), RS); - for (unsigned i = 0, e = SuperRegsVector.size(); i != e; ++i) - OS << getQualifiedName(SuperRegsVector[i]) << ", "; + OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; OS << "0 };\n"; } OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + OS << " { \"NOREG\",\t0,\t0,\t0,\t0,\t0 },\n"; // Now that register alias and sub-registers sets have been emitted, emit the // register descriptors now. @@ -849,19 +442,25 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { const CodeGenRegister &Reg = Regs[i]; OS << " { \""; OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; - if (!RegisterSubRegs[Reg.TheDef].empty()) + if (!Reg.getSubRegs().empty()) OS << Reg.getName() << "_SubRegsSet,\t"; else OS << "Empty_SubRegsSet,\t"; - if (!RegisterSuperRegs[Reg.TheDef].empty()) - OS << Reg.getName() << "_SuperRegsSet },\n"; + if (!Reg.getSuperRegs().empty()) + OS << Reg.getName() << "_SuperRegsSet,\t"; else - OS << "Empty_SuperRegsSet },\n"; + OS << "Empty_SuperRegsSet,\t"; + OS << Reg.CostPerUse << ",\t" + << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } OS << " };\n"; // End of register descriptors... + // Calculate the mapping of subregister+index pairs to physical registers. + // This will also create further anonymous indexes. + unsigned NamedIndices = RegBank.getNumNamedIndices(); + // Emit SubRegIndex names, skipping 0 - const std::vector<Record*> SubRegIndices = Target.getSubRegIndices(); + const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); OS << "\n const char *const SubRegIndexTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); @@ -869,13 +468,21 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "\", \""; } OS << "\" };\n\n"; + + // Emit names of the anonymus subreg indexes. + if (SubRegIndices.size() > NamedIndices) { + OS << " enum {"; + for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) { + OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1; + if (i+1 != e) + OS << ','; + } + OS << "\n };\n\n"; + } OS << "}\n\n"; // End of anonymous namespace... std::string ClassName = Target.getName() + "GenRegisterInfo"; - // Calculate the mapping of subregister+index pairs to physical registers. - RegisterMaps RegMaps; - // Emit the subregister + index mapping function based on the information // calculated above. OS << "unsigned " << ClassName @@ -883,16 +490,16 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegisterMaps::SubRegMap &SRM = RegMaps.inferSubRegIndices(Regs[i].TheDef); + const CodeGenRegister::SubRegMap &SRM = Regs[i].getSubRegs(); if (SRM.empty()) continue; OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; OS << " switch (Index) {\n"; OS << " default: return 0;\n"; - for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(), + for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie; ++ii) OS << " case " << getQualifiedName(ii->first) - << ": return " << getQualifiedName(ii->second) << ";\n"; + << ": return " << getQualifiedName(ii->second->TheDef) << ";\n"; OS << " };\n" << " break;\n"; } OS << " };\n"; @@ -904,13 +511,13 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegisterMaps::SubRegMap &SRM = RegMaps.SubReg[Regs[i].TheDef]; + const CodeGenRegister::SubRegMap &SRM = Regs[i].getSubRegs(); if (SRM.empty()) continue; OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; - for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(), + for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie; ++ii) - OS << " if (SubRegNo == " << getQualifiedName(ii->second) + OS << " if (SubRegNo == " << getQualifiedName(ii->second->TheDef) << ") return " << getQualifiedName(ii->first) << ";\n"; OS << " return 0;\n"; } @@ -919,7 +526,6 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "}\n\n"; // Emit composeSubRegIndices - RegMaps.computeComposites(); OS << "unsigned " << ClassName << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" << " switch (IdxA) {\n" @@ -927,8 +533,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { bool Open = false; for (unsigned j = 0; j != e; ++j) { - if (Record *Comp = RegMaps.Composite.lookup( - std::make_pair(SubRegIndices[i], SubRegIndices[j]))) { + if (Record *Comp = RegBank.getCompositeSubRegIndex(SubRegIndices[i], + SubRegIndices[j])) { if (!Open) { OS << " case " << getQualifiedName(SubRegIndices[i]) << ": switch(IdxB) {\n default: return IdxB;\n"; @@ -949,9 +555,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1 << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexTable,\n" - << " CallFrameSetupOpcode, CallFrameDestroyOpcode,\n" - << " SubregHashTable, SubregHashTableSize,\n" - << " AliasesHashTable, AliasesHashTableSize) {\n" + << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {\n" << "}\n\n"; // Collect all information about dwarf register numbers @@ -974,6 +578,44 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); + // Emit reverse information about the dwarf register numbers. + OS << "int " << ClassName << "::getLLVMRegNumFull(unsigned DwarfRegNum, " + << "unsigned Flavour) const {\n" + << " switch (Flavour) {\n" + << " default:\n" + << " assert(0 && \"Unknown DWARF flavour\");\n" + << " return -1;\n"; + + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << " case " << i << ":\n" + << " switch (DwarfRegNum) {\n" + << " default:\n" + << " assert(0 && \"Invalid DwarfRegNum\");\n" + << " return -1;\n"; + + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int DwarfRegNo = I->second[i]; + if (DwarfRegNo >= 0) + OS << " case " << DwarfRegNo << ":\n" + << " return " << getQualifiedName(I->first) << ";\n"; + } + OS << " };\n"; + } + + OS << " };\n}\n\n"; + + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i].TheDef; + const RecordVal *V = Reg->getValue("DwarfAlias"); + if (!V || !V->getValue()) + continue; + + DefInit *DI = dynamic_cast<DefInit*>(V->getValue()); + Record *Alias = DI->getDef(); + DwarfRegNums[Reg] = DwarfRegNums[Alias]; + } + // Emit information about the dwarf register numbers. OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const {\n" @@ -995,13 +637,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (DwarfRegNumsMapTy::iterator I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { int RegNo = I->second[i]; - if (RegNo != -2) - OS << " case " << getQualifiedName(I->first) << ":\n" - << " return " << RegNo << ";\n"; - else - OS << " case " << getQualifiedName(I->first) << ":\n" - << " assert(0 && \"Invalid register for this mode\");\n" - << " return -1;\n"; + OS << " case " << getQualifiedName(I->first) << ":\n" + << " return " << RegNo << ";\n"; } OS << " };\n"; } diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp new file mode 100644 index 0000000..509d2f3 --- /dev/null +++ b/utils/TableGen/SetTheory.cpp @@ -0,0 +1,275 @@ +//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. +// +//===----------------------------------------------------------------------===// + +#include "SetTheory.h" +#include "Record.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +// Define the standard operators. +namespace { + +typedef SetTheory::RecSet RecSet; +typedef SetTheory::RecVec RecVec; + +// (add a, b, ...) Evaluate and union all arguments. +struct AddOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts); + } +}; + +// (sub Add, Sub, ...) Set difference. +struct SubOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() < 2) + throw "Set difference needs at least two arguments: " + + Expr->getAsString(); + RecSet Add, Sub; + ST.evaluate(*Expr->arg_begin(), Add); + ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub); + for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) + if (!Sub.count(*I)) + Elts.insert(*I); + } +}; + +// (and S1, S2) Set intersection. +struct AndOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 2) + throw "Set intersection requires two arguments: " + Expr->getAsString(); + RecSet S1, S2; + ST.evaluate(Expr->arg_begin()[0], S1); + ST.evaluate(Expr->arg_begin()[1], S2); + for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) + if (S2.count(*I)) + Elts.insert(*I); + } +}; + +// SetIntBinOp - Abstract base class for (Op S, N) operators. +struct SetIntBinOp : public SetTheory::Operator { + virtual void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) =0; + + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 2) + throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString(); + RecSet Set; + ST.evaluate(Expr->arg_begin()[0], Set); + IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]); + if (!II) + throw "Second argument must be an integer: " + Expr->getAsString(); + apply2(ST, Expr, Set, II->getValue(), Elts); + } +}; + +// (shl S, N) Shift left, remove the first N elements. +struct ShlOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N < 0) + throw "Positive shift required: " + Expr->getAsString(); + if (unsigned(N) < Set.size()) + Elts.insert(Set.begin() + N, Set.end()); + } +}; + +// (trunc S, N) Truncate after the first N elements. +struct TruncOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N < 0) + throw "Positive length required: " + Expr->getAsString(); + if (unsigned(N) > Set.size()) + N = Set.size(); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// Left/right rotation. +struct RotOp : public SetIntBinOp { + const bool Reverse; + + RotOp(bool Rev) : Reverse(Rev) {} + + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (Reverse) + N = -N; + // N > 0 -> rotate left, N < 0 -> rotate right. + if (Set.empty()) + return; + if (N < 0) + N = Set.size() - (-N % Set.size()); + else + N %= Set.size(); + Elts.insert(Set.begin() + N, Set.end()); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// (decimate S, N) Pick every N'th element of S. +struct DecimateOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N <= 0) + throw "Positive stride required: " + Expr->getAsString(); + for (unsigned I = 0; I < Set.size(); I += N) + Elts.insert(Set[I]); + } +}; + +// (sequence "Format", From, To) Generate a sequence of records by name. +struct SequenceOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 3) + throw "Bad args to (sequence \"Format\", From, To): " + + Expr->getAsString(); + std::string Format; + if (StringInit *SI = dynamic_cast<StringInit*>(Expr->arg_begin()[0])) + Format = SI->getValue(); + else + throw "Format must be a string: " + Expr->getAsString(); + + int64_t From, To; + if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1])) + From = II->getValue(); + else + throw "From must be an integer: " + Expr->getAsString(); + if (From < 0 || From >= (1 << 30)) + throw "From out of range"; + + if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[2])) + To = II->getValue(); + else + throw "From must be an integer: " + Expr->getAsString(); + if (To < 0 || To >= (1 << 30)) + throw "To out of range"; + + RecordKeeper &Records = + dynamic_cast<DefInit&>(*Expr->getOperator()).getDef()->getRecords(); + + int Step = From <= To ? 1 : -1; + for (To += Step; From != To; From += Step) { + std::string Name; + raw_string_ostream OS(Name); + OS << format(Format.c_str(), unsigned(From)); + Record *Rec = Records.getDef(OS.str()); + if (!Rec) + throw "No def named '" + Name + "': " + Expr->getAsString(); + // Try to reevaluate Rec in case it is a set. + if (const RecVec *Result = ST.expand(Rec)) + Elts.insert(Result->begin(), Result->end()); + else + Elts.insert(Rec); + } + } +}; + +// Expand a Def into a set by evaluating one of its fields. +struct FieldExpander : public SetTheory::Expander { + StringRef FieldName; + + FieldExpander(StringRef fn) : FieldName(fn) {} + + void expand(SetTheory &ST, Record *Def, RecSet &Elts) { + ST.evaluate(Def->getValueInit(FieldName), Elts); + } +}; +} // end anonymous namespace + +SetTheory::SetTheory() { + addOperator("add", new AddOp); + addOperator("sub", new SubOp); + addOperator("and", new AndOp); + addOperator("shl", new ShlOp); + addOperator("trunc", new TruncOp); + addOperator("rotl", new RotOp(false)); + addOperator("rotr", new RotOp(true)); + addOperator("decimate", new DecimateOp); + addOperator("sequence", new SequenceOp); +} + +void SetTheory::addOperator(StringRef Name, Operator *Op) { + Operators[Name] = Op; +} + +void SetTheory::addExpander(StringRef ClassName, Expander *E) { + Expanders[ClassName] = E; +} + +void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { + addExpander(ClassName, new FieldExpander(FieldName)); +} + +void SetTheory::evaluate(Init *Expr, RecSet &Elts) { + // A def in a list can be a just an element, or it may expand. + if (DefInit *Def = dynamic_cast<DefInit*>(Expr)) { + if (const RecVec *Result = expand(Def->getDef())) + return Elts.insert(Result->begin(), Result->end()); + Elts.insert(Def->getDef()); + return; + } + + // Lists simply expand. + if (ListInit *LI = dynamic_cast<ListInit*>(Expr)) + return evaluate(LI->begin(), LI->end(), Elts); + + // Anything else must be a DAG. + DagInit *DagExpr = dynamic_cast<DagInit*>(Expr); + if (!DagExpr) + throw "Invalid set element: " + Expr->getAsString(); + DefInit *OpInit = dynamic_cast<DefInit*>(DagExpr->getOperator()); + if (!OpInit) + throw "Bad set expression: " + Expr->getAsString(); + Operator *Op = Operators.lookup(OpInit->getDef()->getName()); + if (!Op) + throw "Unknown set operator: " + Expr->getAsString(); + Op->apply(*this, DagExpr, Elts); +} + +const RecVec *SetTheory::expand(Record *Set) { + // Check existing entries for Set and return early. + ExpandMap::iterator I = Expansions.find(Set); + if (I != Expansions.end()) + return &I->second; + + // This is the first time we see Set. Find a suitable expander. + try { + const std::vector<Record*> &SC = Set->getSuperClasses(); + for (unsigned i = 0, e = SC.size(); i != e; ++i) + if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { + // This breaks recursive definitions. + RecVec &EltVec = Expansions[Set]; + RecSet Elts; + Exp->expand(*this, Set, Elts); + EltVec.assign(Elts.begin(), Elts.end()); + return &EltVec; + } + } catch (const std::string &Error) { + throw TGError(Set->getLoc(), Error); + } + + // Set is not expandable. + return 0; +} + diff --git a/utils/TableGen/SetTheory.h b/utils/TableGen/SetTheory.h new file mode 100644 index 0000000..e37a76e --- /dev/null +++ b/utils/TableGen/SetTheory.h @@ -0,0 +1,136 @@ +//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. Operators for standard set operations are +// predefined, and it is possible to add special purpose set operators as well. +// +// The user may define named sets as Records of predefined classes. Set +// expanders can be added to a SetTheory instance to teach it how to find the +// elements of such a named set. +// +// These are the predefined operators. The argument lists can be individual +// elements (defs), other sets (defs of expandable classes), lists, or DAG +// expressions that are evaluated recursively. +// +// - (add S1, S2 ...) Union sets. This is also how sets are created from element +// lists. +// +// - (sub S1, S2, ...) Set difference. Every element in S1 except for the +// elements in S2, ... +// +// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. +// +// - (shl S, N) Shift left. Remove the first N elements from S. +// +// - (trunc S, N) Truncate. The first N elements of S. +// +// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). +// +// - (rotr S, N) Rotate right. +// +// - (decimate S, N) Decimate S by picking every N'th element, starting with +// the first one. For instance, (decimate S, 2) returns the even elements of +// S. +// +// - (sequence "Format", From, To) Generate a sequence of defs with printf. +// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] +// +//===----------------------------------------------------------------------===// + +#ifndef SETTHEORY_H +#define SETTHEORY_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SetVector.h" +#include <map> +#include <vector> + +namespace llvm { + +class DagInit; +struct Init; +class Record; +class RecordKeeper; + +class SetTheory { +public: + typedef std::vector<Record*> RecVec; + typedef SmallSetVector<Record*, 16> RecSet; + + /// Operator - A callback representing a DAG operator. + struct Operator { + virtual ~Operator() {} + + /// apply - Apply this operator to Expr's arguments and insert the result + /// in Elts. + virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts) =0; + }; + + /// Expander - A callback function that can transform a Record representing a + /// set into a fully expanded list of elements. Expanders provide a way for + /// users to define named sets that can be used in DAG expressions. + struct Expander { + virtual ~Expander() {} + + virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; + }; + +private: + // Map set defs to their fully expanded contents. This serves as a memoization + // cache and it makes it possible to return const references on queries. + typedef std::map<Record*, RecVec> ExpandMap; + ExpandMap Expansions; + + // Known DAG operators by name. + StringMap<Operator*> Operators; + + // Typed expanders by class name. + StringMap<Expander*> Expanders; + +public: + /// Create a SetTheory instance with only the standard operators. + SetTheory(); + + /// addExpander - Add an expander for Records with the named super class. + void addExpander(StringRef ClassName, Expander*); + + /// addFieldExpander - Add an expander for ClassName that simply evaluates + /// FieldName in the Record to get the set elements. That is all that is + /// needed for a class like: + /// + /// class Set<dag d> { + /// dag Elts = d; + /// } + /// + void addFieldExpander(StringRef ClassName, StringRef FieldName); + + /// addOperator - Add a DAG operator. + void addOperator(StringRef Name, Operator*); + + /// evaluate - Evaluate Expr and append the resulting set to Elts. + void evaluate(Init *Expr, RecSet &Elts); + + /// evaluate - Evaluate a sequence of Inits and append to Elts. + template<typename Iter> + void evaluate(Iter begin, Iter end, RecSet &Elts) { + while (begin != end) + evaluate(*begin++, Elts); + } + + /// expand - Expand a record into a set of elements if possible. Return a + /// pointer to the expanded elements, or NULL if Set cannot be expanded + /// further. + const RecVec *expand(Record *Set); +}; + +} // end namespace llvm + +#endif + diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 8ca4b1c..928fa4b 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -33,7 +33,13 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, OS << "enum {\n"; // For each record - for (unsigned i = 0, N = DefList.size(); i < N;) { + unsigned N = DefList.size(); + if (N > 64) { + errs() << "Too many (> 64) subtarget features!\n"; + exit(1); + } + + for (unsigned i = 0; i < N;) { // Next record Record *Def = DefList[i]; @@ -41,7 +47,7 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, OS << " " << Def->getName(); // If bit flags then emit expression (1 << i) - if (isBits) OS << " = " << " 1 << " << i; + if (isBits) OS << " = " << " 1ULL << " << i; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; @@ -88,7 +94,7 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { Feature->getValueAsListOfDefs("Implies"); if (ImpliesList.empty()) { - OS << "0"; + OS << "0ULL"; } else { for (unsigned j = 0, M = ImpliesList.size(); j < M;) { OS << ImpliesList[j]->getName(); @@ -142,7 +148,7 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { << "\"Select the " << Name << " processor\", "; if (FeatureList.empty()) { - OS << "0"; + OS << "0ULL"; } else { for (unsigned j = 0, M = FeatureList.size(); j < M;) { OS << FeatureList[j]->getName(); @@ -151,7 +157,7 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { } // The "0" is for the "implies" section of this data structure. - OS << ", 0 }"; + OS << ", 0ULL }"; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; @@ -608,7 +614,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n" << " SubtargetFeatures Features(FS);\n" << " Features.setCPUIfNone(CPU);\n" - << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + << " uint64_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" << " FeatureKV, FeatureKVSize);\n"; for (unsigned i = 0; i < Features.size(); i++) { diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index 82d2b64..572c36d 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -267,14 +267,17 @@ bool TGLexer::LexInclude() { // Get the string. std::string Filename = CurStrVal; + std::string IncludedFile; - CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr)); + CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr), + IncludedFile); if (CurBuffer == -1) { PrintError(getLoc(), "Could not find include file '" + Filename + "'"); return true; } + Dependencies.push_back(IncludedFile); // Save the line number and lex buffer of the includer. CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); CurPtr = CurBuf->getBufferStart(); diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index 8859479..c2a6453 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -15,8 +15,8 @@ #define TGLEXER_H #include "llvm/Support/DataTypes.h" -#include <vector> #include <string> +#include <vector> #include <cassert> namespace llvm { @@ -72,6 +72,8 @@ class TGLexer { /// CurBuffer - This is the current buffer index we're lexing from as managed /// by the SourceMgr object. int CurBuffer; + /// Dependencies - This is the list of all included files. + std::vector<std::string> Dependencies; public: TGLexer(SourceMgr &SrcMgr); @@ -80,6 +82,10 @@ public: tgtok::TokKind Lex() { return CurCode = LexToken(); } + + const std::vector<std::string> &getDependencies() const { + return Dependencies; + } tgtok::TokKind getCode() const { return CurCode; } diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h index 9cdf68f..419a99b 100644 --- a/utils/TableGen/TGParser.h +++ b/utils/TableGen/TGParser.h @@ -66,6 +66,9 @@ public: bool TokError(const Twine &Msg) const { return Error(Lex.getLoc(), Msg); } + const std::vector<std::string> &getDependencies() const { + return Lex.getDependencies(); + } private: // Semantic analysis methods. bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV); bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName, diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp index 122d085..af0d9f4 100644 --- a/utils/TableGen/TGValueTypes.cpp +++ b/utils/TableGen/TGValueTypes.cpp @@ -16,7 +16,6 @@ #include "llvm/CodeGen/ValueTypes.h" #include <map> -#include <vector> using namespace llvm; namespace llvm { diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 3b7dc01..4e4da36 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -37,6 +37,7 @@ #include "RegisterInfoEmitter.h" #include "ARMDecoderEmitter.h" #include "SubtargetEmitter.h" +#include "SetTheory.h" #include "TGParser.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" @@ -65,6 +66,7 @@ enum ActionType { GenClangAttrSpellingList, GenClangDiagsDefs, GenClangDiagGroups, + GenClangDiagsIndexName, GenClangDeclNodes, GenClangStmtNodes, GenClangSACheckers, @@ -79,7 +81,8 @@ enum ActionType { GenArmNeon, GenArmNeonSema, GenArmNeonTest, - PrintEnums + PrintEnums, + PrintSets }; namespace { @@ -133,12 +136,16 @@ namespace { "Generate clang PCH attribute reader"), clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write", "Generate clang PCH attribute writer"), - clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list", + clEnumValN(GenClangAttrSpellingList, + "gen-clang-attr-spelling-list", "Generate a clang attribute spelling list"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", "Generate Clang diagnostic groups"), + clEnumValN(GenClangDiagsIndexName, + "gen-clang-diags-index-name", + "Generate Clang diagnostic name index"), clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", "Generate Clang AST declaration nodes"), clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", @@ -157,6 +164,8 @@ namespace { "Generate ARM NEON tests for clang"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), + clEnumValN(PrintSets, "print-sets", + "Print expanded sets for testing DAG exprs"), clEnumValEnd)); cl::opt<std::string> @@ -168,6 +177,10 @@ namespace { cl::init("-")); cl::opt<std::string> + DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"), + cl::init("")); + + cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); cl::list<std::string> @@ -187,34 +200,6 @@ void llvm::PrintError(SMLoc ErrorLoc, const Twine &Msg) { SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); } - - -/// ParseFile - this function begins the parsing of the specified tablegen -/// file. -static bool ParseFile(const std::string &Filename, - const std::vector<std::string> &IncludeDirs, - SourceMgr &SrcMgr, - RecordKeeper &Records) { - OwningPtr<MemoryBuffer> File; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { - errs() << "Could not open input file '" << Filename << "': " - << ec.message() <<"\n"; - return true; - } - MemoryBuffer *F = File.take(); - - // Tell SrcMgr about this buffer, which is what TGParser will pick up. - SrcMgr.AddNewSourceBuffer(F, SMLoc()); - - // Record the location of the include directory so that the lexer can find - // it later. - SrcMgr.setIncludeDirs(IncludeDirs); - - TGParser Parser(SrcMgr, Records); - - return Parser.ParseFile(); -} - int main(int argc, char **argv) { RecordKeeper Records; @@ -223,19 +208,57 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); - // Parse the input file. - if (ParseFile(InputFilename, IncludeDirs, SrcMgr, Records)) - return 1; + try { + // Parse the input file. + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { + errs() << "Could not open input file '" << InputFilename << "': " + << ec.message() <<"\n"; + return 1; + } + MemoryBuffer *F = File.take(); + + // Tell SrcMgr about this buffer, which is what TGParser will pick up. + SrcMgr.AddNewSourceBuffer(F, SMLoc()); + + // Record the location of the include directory so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); - std::string Error; - tool_output_file Out(OutputFilename.c_str(), Error); - if (!Error.empty()) { - errs() << argv[0] << ": error opening " << OutputFilename - << ":" << Error << "\n"; - return 1; - } + TGParser Parser(SrcMgr, Records); + + if (Parser.ParseFile()) + return 1; + + std::string Error; + tool_output_file Out(OutputFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv[0] << ": error opening " << OutputFilename + << ":" << Error << "\n"; + return 1; + } + if (!DependFilename.empty()) { + if (OutputFilename == "-") { + errs() << argv[0] << ": the option -d must be used together with -o\n"; + return 1; + } + tool_output_file DepOut(DependFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv[0] << ": error opening " << DependFilename + << ":" << Error << "\n"; + return 1; + } + DepOut.os() << DependFilename << ":"; + const std::vector<std::string> &Dependencies = Parser.getDependencies(); + for (std::vector<std::string>::const_iterator I = Dependencies.begin(), + E = Dependencies.end(); + I != E; ++I) { + DepOut.os() << " " << (*I); + } + DepOut.os() << "\n"; + DepOut.keep(); + } - try { switch (Action) { case PrintRecords: Out.os() << Records; // No argument, dump all contents @@ -295,6 +318,9 @@ int main(int argc, char **argv) { case GenClangDiagGroups: ClangDiagGroupsEmitter(Records).run(Out.os()); break; + case GenClangDiagsIndexName: + ClangDiagsIndexNameEmitter(Records).run(Out.os()); + break; case GenClangDeclNodes: ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); ClangDeclContextEmitter(Records).run(Out.os()); @@ -352,6 +378,21 @@ int main(int argc, char **argv) { Out.os() << "\n"; break; } + case PrintSets: + { + SetTheory Sets; + Sets.addFieldExpander("Set", "Elements"); + std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) { + Out.os() << Recs[i]->getName() << " = ["; + const std::vector<Record*> *Elts = Sets.expand(Recs[i]); + assert(Elts && "Couldn't expand Set instance"); + for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) + Out.os() << ' ' << (*Elts)[ei]->getName(); + Out.os() << " ]\n"; + } + break; + } default: assert(1 && "Invalid Action"); return 1; diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index fe4ad6f..d16ebfc 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -79,7 +79,7 @@ private: /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte. /// nnnn is the number of a table for looking up these values. The tables - /// are writen separately so that tables consisting entirely of zeros will + /// are written separately so that tables consisting entirely of zeros will /// not be duplicated. (These all have the name modRMEmptyTable.) A table /// is printed as: /// diff --git a/utils/buildit/GNUmakefile b/utils/buildit/GNUmakefile index 5140e15..470ee76 100644 --- a/utils/buildit/GNUmakefile +++ b/utils/buildit/GNUmakefile @@ -6,7 +6,7 @@ # # You can specify TARGETS=ppc (or i386) on the buildit command line to limit the # build to just one target. The default is for ppc and i386. The compiler -# targetted at this host gets built anyway, but not installed unless it's listed +# targeted at this host gets built anyway, but not installed unless it's listed # in TARGETS. # Include the set of standard Apple makefile definitions. diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 80d0ba1..83603cc 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -473,9 +473,11 @@ def parseIntegratedTestScript(test, normalize_slashes=False): if script[-1][-1] == '\\': return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')") - # Check that we have the required features: + # Check that we have the required features or build modes: missing_required_features = [f for f in requires - if f not in test.config.available_features] + if f not in test.config.available_features + and f not in test.config.llvm_build_modes] + if missing_required_features: msg = ', '.join(missing_required_features) return (Test.UNSUPPORTED, diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py index 25bb341..2d8d3d0 100644 --- a/utils/lit/lit/TestingConfig.py +++ b/utils/lit/lit/TestingConfig.py @@ -74,6 +74,7 @@ class TestingConfig: def clone(self, path): # FIXME: Chain implementations? + # See attribute chaining in finish() # # FIXME: Allow extra parameters? cfg = TestingConfig(self, self.name, self.suffixes, self.test_format, @@ -101,3 +102,9 @@ class TestingConfig: # files. Should we distinguish them? self.test_source_root = str(self.test_source_root) self.excludes = set(self.excludes) + + # chain attributes by copying them + if self.parent: + for k,v in vars(self.parent).items(): + if not hasattr(self, k): + setattr(self, k, v) diff --git a/utils/lit/setup.py b/utils/lit/setup.py index 738ee23..a94e6ea 100644 --- a/utils/lit/setup.py +++ b/utils/lit/setup.py @@ -38,7 +38,7 @@ Features Documentation ============= -The offical *lit* documentation is in the man page, available online at the LLVM +The official *lit* documentation is in the man page, available online at the LLVM Command Guide: http://llvm.org/cmds/lit.html. diff --git a/utils/llvm.grm b/utils/llvm.grm index 9d6bdf7..3f33702 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -172,6 +172,8 @@ FuncAttr ::= noreturn | optsize | ssp | sspreq + | hotpatch + | nonlazybind ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; diff --git a/utils/profile.pl b/utils/profile.pl index 3180115..782e5dc 100755 --- a/utils/profile.pl +++ b/utils/profile.pl @@ -65,7 +65,7 @@ shift @ARGV; my $libdir = `llvm-config --libdir`; chomp $libdir; -my $LibProfPath = $libdir . "/profile_rt.so"; +my $LibProfPath = $libdir . "/libprofile_rt.so"; system "opt -q -f $ProfilePass $BytecodeFile -o $BytecodeFile.inst"; system "lli -fake-argv0 '$BytecodeFile' -load $LibProfPath " . diff --git a/utils/show-diagnostics b/utils/show-diagnostics new file mode 100755 index 0000000..3a69793 --- /dev/null +++ b/utils/show-diagnostics @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +import plistlib + +def main(): + from optparse import OptionParser, OptionGroup + parser = OptionParser("""\ +usage: %prog [options] <path> + +Utility for dumping Clang-style logged diagnostics.\ +""") + (opts, args) = parser.parse_args() + + if len(args) != 1: + parser.error("invalid number of arguments") + + path, = args + + # Read the diagnostics log. + f = open(path) + try: + data = f.read() + finally: + f.close() + + # Complete the plist (the log itself is just the chunks). + data = """\ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \ + "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<array> +%s +</array> +</plist>""" % data + + # Load the diagnostics. + diags = plistlib.readPlistFromString(data) + + # Print out the diagnostics. + print + print "**** BUILD DIAGNOSTICS ****" + for i, file_diags in enumerate(diags): + file = file_diags.get('main-file') + print "*** %s ***" % file + for d in file_diags.get('diagnostics', ()): + print "%s:%s:%s: %s: %s" % ( + d.get('filename'), d.get('line'), d.get('column'), + d.get('level'), d.get('message')) + +if __name__ == "__main__": + main() diff --git a/utils/unittest/googletest/gtest-filepath.cc b/utils/unittest/googletest/gtest-filepath.cc index c1ef918..8d1d67e 100644 --- a/utils/unittest/googletest/gtest-filepath.cc +++ b/utils/unittest/googletest/gtest-filepath.cc @@ -123,7 +123,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const { return *this; } -// Returns a pointer to the last occurence of a valid path separator in +// Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FilePath::FindLastPathSeparator() const { diff --git a/utils/unittest/googletest/gtest.cc b/utils/unittest/googletest/gtest.cc index 51732af..9aa5441 100644 --- a/utils/unittest/googletest/gtest.cc +++ b/utils/unittest/googletest/gtest.cc @@ -1415,7 +1415,7 @@ AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT // Utility functions for encoding Unicode text (wide strings) in // UTF-8. -// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8 // like this: // // Code-point length Encoding diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h index 4b76d79..efbc176 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h @@ -196,7 +196,7 @@ class GTEST_API_ FilePath { void Normalize(); - // Returns a pointer to the last occurence of a valid path separator in + // Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FindLastPathSeparator() const; diff --git a/utils/valgrind/i386-pc-linux-gnu.supp b/utils/valgrind/i386-pc-linux-gnu.supp index 0509791..ddd0a08 100644 --- a/utils/valgrind/i386-pc-linux-gnu.supp +++ b/utils/valgrind/i386-pc-linux-gnu.supp @@ -39,3 +39,10 @@ fun:malloc obj:/usr/bin/python* } + +{ + We don't care about anything ld.so does. + Memcheck:Cond + obj:/lib/ld*.so +} + diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp index 7b2dd45..3d15d71 100644 --- a/utils/valgrind/x86_64-pc-linux-gnu.supp +++ b/utils/valgrind/x86_64-pc-linux-gnu.supp @@ -44,3 +44,10 @@ fun:malloc obj:/usr/bin/python* } + +{ + We don't care about anything ld.so does. + Memcheck:Cond + obj:/lib/ld*.so +} + |