Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -80,6 +80,25 @@ // FctOverloadMap and TypeMap. void GetOverloads(); + // Helper function for BuiltinNameEmitter::GroupFctBySignature. + // When comparing two lists of signatures, checks OpenCL versions and + // function extension are equal for each signature. + // \param Candidate (in) The entry in the SignatureListMap to check + // + // \param SignatureList (in) The list of signatures of the considered function. + // + // \returns true if the two lists of signatures are identic + bool CheckSignature(SmallVector* Candidate, + std::vector> &SignatureList); + + // Some builtin functions have the same list of signatures. For instance, the + // "sin" and "cos" functions. To save space in the BuiltinTable, the + // "isOpenCLBuiltin" function will have the same output for these two + // function name. + // This function groups functions with the same list of signatures by + // populating the SignatureListMap. + void GroupFctBySignature(); + // Emit the FctExtensionTable and the TypeExtensionTable. // FctExtensionTable maps enums OpenCLFctExtensionID to their extension. // TypeExtensionTable maps OpenCLTypeID enums (not being generic types) to @@ -111,9 +130,10 @@ // each function. // E.g.: // // acos - // { 2, 0, "", 100 }, - // This means that the signature of this acos overload has 1 argument (+1 for - // the return type), stored at index 0 in the OpenCLSignature table. + // { 1, 0, "", 100 }, + // This means that the signature of acos, defined in OpenCL version 1.0 and + // not belonging to any extension, has a signature with 0 argument (only one + // return type), and is stored at index 0 in the SignatureTable. void EmitBuiltinTable(); // Emit a StringMatcher function to check whether a function name is an @@ -178,6 +198,29 @@ // Same as TypeExtensionList, but for generic types only. std::vector GenTypeExtensionList; + + // Map an ordered vector of signatures to the definitions of the same list + // of signatures, and to a list of function names that have this list of + // signatures. + // E.g.: + // If the "cos" and "sin" functions had only three signatures. These + // signatures being at the index Ix in the SignatureTable: + // cos | sin | Signature | Index + // float cos(float) | float sin(float) | Signature1 | I1 + // double cos(double) | double sin(double) | Signature2 | I2 + // half cos(half) | half sin(half) | Signature3 | I3 + // + // Then we will create a mapping of the vector of signature: + // SignatureListMap() = + // <<, + // , + // >, + // <"cos", "sin">> + // The function "tan", having the same signatures, would be inserted at the + // same entry (). + MapVector*, + std::pair>, + std::vector*>> SignatureListMap; }; } // namespace @@ -192,6 +235,7 @@ // Parse the Records to populate the internal lists GetOverloads(); + GroupFctBySignature(); // Emit data strucures EmitExtensionTable(); @@ -443,11 +487,15 @@ unsigned Index = 0; OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n"; - for (const auto &FOM : FctOverloadMap) { + for (const auto &SLM : SignatureListMap) { - OS << "// " << Index << " " << FOM.first << "\n"; + OS << "// " << Index << " "; + for (const auto &Name : *(SLM.second.second)) { + OS << Name << ", "; + } + OS << "\n"; - for (const auto &Overload : FOM.second) { + for (const auto &Overload : SLM.second.first) { OS << " { " << Overload.second << ", " << Overload.first->getValueAsListOfDefs("Signature").size() << ", " @@ -462,21 +510,89 @@ } +bool BuiltinNameEmitter::CheckSignature( + SmallVector* Candidate, + std::vector> &SignatureList) { + // The two lists have the same list of signatures, but there are other + // fields to check + const Record *Rec, *Rec2; + for (unsigned Index = 0; Index < Candidate->size(); Index++) { + Rec = SignatureList[Index].first; + Rec2 = (SignatureListMap.find(Candidate)->second.first)[Index].first; + if (Rec->getValueAsDef("MinVersion")->getValueAsInt("Name") == + Rec2->getValueAsDef("MinVersion")->getValueAsInt("Name") && + Rec->getValueAsDef("MaxVersion")->getValueAsInt("Name") == + Rec2->getValueAsDef("MaxVersion")->getValueAsInt("Name") && + Rec->getValueAsDef("Extension")->getValueAsString("ID") == + Rec2->getValueAsDef("Extension")->getValueAsString("ID")) { + return true; + } + } + return false; +} + + +void BuiltinNameEmitter::GroupFctBySignature() { + // Available lists of signatures + std::vector*> SignatureListPool; + bool FoundSimilar = false; + + for (auto &Fct : FctOverloadMap) { + FoundSimilar = false; + + // Gather all the signatures for the current function + SmallVector *CurSignatureList = + new SmallVector(); + for (const auto &Signature : Fct.second) { + CurSignatureList->push_back(Signature.second); + } + // Order the list to facilitate the future comparisons + std::sort(CurSignatureList->begin(), CurSignatureList->end()); + + // Check if another function has the same list of signatures + // If yes, we just need to add the name of the function + for (auto *Candidate : SignatureListPool) { + if (Candidate->size() == CurSignatureList->size()) { + if (*Candidate == *CurSignatureList) { + if (CheckSignature(Candidate, Fct.second)) { + SignatureListMap.find(Candidate)->second.second->push_back(Fct.first); + FoundSimilar = true; + } + } + } + } + + // else, add a new entry + if (!FoundSimilar) { + std::vector *NewStringList = new std::vector(); + NewStringList->push_back(Fct.first); + SignatureListMap[CurSignatureList] = + std::make_pair(Fct.second, NewStringList); + SignatureListPool.push_back(CurSignatureList); + } + } +} + + void BuiltinNameEmitter::EmitStringMatcher() { std::vector ValidBuiltins; unsigned CumulativeIndex = 1; - for (auto &i : FctOverloadMap) { - auto &Ov = i.second; - std::string RetStmt; - raw_string_ostream SS(RetStmt); - SS << "return std::make_pair(" << CumulativeIndex << ", " << Ov.size() - << ");"; - SS.flush(); - CumulativeIndex += Ov.size(); - - ValidBuiltins.push_back(StringMatcher::StringPair(i.first, RetStmt)); - } + for (const auto &SLM : SignatureListMap) { + const auto &Ovl = SLM.second.first; + + // Function names with the same list of signatures have the reference the + // same frame in the BuiltinTable. + for (const auto &FctName : *(SLM.second.second)) { + std::string RetStmt; + raw_string_ostream SS(RetStmt); + SS << "return std::make_pair(" << CumulativeIndex << ", " << Ovl.size() + << ");"; + SS.flush(); + ValidBuiltins.push_back(StringMatcher::StringPair(FctName, RetStmt)); + } + CumulativeIndex += Ovl.size(); + } OS << R"(