Switch TargetInfo::getTargetDefines from using an std::map<std::string, ...> to using

a llvm::StringMap.  This dramatically reduces the startup time of the preprocessor,
speeding up -Eonly on xalankbmk by 2.2%.

llvm-svn: 40396
This commit is contained in:
Chris Lattner 2007-07-22 20:11:46 +00:00
parent 3284ad1b1f
commit a81b336ba8
1 changed files with 54 additions and 32 deletions

View File

@ -14,7 +14,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/Builtins.h"
#include <map>
#include "llvm/ADT/StringMap.h"
#include <set>
using namespace clang;
@ -32,20 +32,24 @@ void TargetInfo::DiagnoseNonPortability(SourceLocation Loc, unsigned DiagKind) {
/// GetTargetDefineMap - Get the set of target #defines in an associative
/// collection for easy lookup.
static void GetTargetDefineMap(const TargetInfoImpl *Target,
std::map<std::string, std::string> &Map) {
llvm::StringMap<std::string> &Map) {
std::vector<std::string> PrimaryDefines;
Target->getTargetDefines(PrimaryDefines);
while (!PrimaryDefines.empty()) {
const char *Str = PrimaryDefines.back().c_str();
std::string &PrimDefineStr = PrimaryDefines.back();
const char *Str = PrimDefineStr.c_str();
const char *StrEnd = Str+PrimDefineStr.size();
if (const char *Equal = strchr(Str, '=')) {
// Split at the '='.
Map.insert(std::make_pair(std::string(Str, Equal),
std::string(Equal+1,
Str+PrimaryDefines.back().size())));
std::string &Entry = Map.GetOrCreateValue(Str, Equal).getValue();
Entry = std::string(Equal+1, StrEnd);
} else {
// Remember "macroname=1".
Map.insert(std::make_pair(PrimaryDefines.back(), std::string("1")));
std::string &Entry = Map.GetOrCreateValue(Str, StrEnd).getValue();
Entry = "1";
}
PrimaryDefines.pop_back();
}
@ -64,12 +68,12 @@ void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
// of target-specific macros.
// Get the set of primary #defines.
std::map<std::string, std::string> PrimaryDefines;
llvm::StringMap<std::string> PrimaryDefines;
GetTargetDefineMap(PrimaryTarget, PrimaryDefines);
// If we have no secondary targets, be a bit more efficient.
if (SecondaryTargets.empty()) {
for (std::map<std::string, std::string>::iterator I =
for (llvm::StringMap<std::string>::iterator I =
PrimaryDefines.begin(), E = PrimaryDefines.end(); I != E; ++I) {
// If this define is non-portable, turn it into #define_target, otherwise
// just use #define.
@ -77,42 +81,47 @@ void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
// Insert "defname defvalue\n".
Buffer.insert(Buffer.end(), I->first.begin(), I->first.end());
const char *KeyStart = I->getKeyData();
const char *KeyEnd = KeyStart + I->getKeyLength();
Buffer.insert(Buffer.end(), KeyStart, KeyEnd);
Buffer.push_back(' ');
Buffer.insert(Buffer.end(), I->second.begin(), I->second.end());
Buffer.insert(Buffer.end(), I->getValue().begin(), I->getValue().end());
Buffer.push_back('\n');
}
return;
}
// Get the sets of secondary #defines.
std::vector<std::map<std::string, std::string> > SecondaryDefines;
SecondaryDefines.resize(SecondaryTargets.size());
llvm::StringMap<std::string> *SecondaryDefines
= new llvm::StringMap<std::string>[SecondaryTargets.size()];
for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i)
GetTargetDefineMap(SecondaryTargets[i], SecondaryDefines[i]);
// Loop over all defines in the primary target, processing them until we run
// out.
while (!PrimaryDefines.empty()) {
std::string DefineName = PrimaryDefines.begin()->first;
std::string DefineValue = PrimaryDefines.begin()->second;
PrimaryDefines.erase(PrimaryDefines.begin());
for (llvm::StringMap<std::string>::iterator PDI =
PrimaryDefines.begin(), E = PrimaryDefines.end(); PDI != E; ++PDI) {
std::string DefineName(PDI->getKeyData(),
PDI->getKeyData() + PDI->getKeyLength());
std::string DefineValue = PDI->getValue();
// Check to see whether all secondary targets have this #define and whether
// it is to the same value. Remember if not, but remove the #define from
// their collection in any case if they have it.
bool isPortable = true;
for (unsigned i = 0, e = SecondaryDefines.size(); i != e; ++i) {
std::map<std::string, std::string>::iterator I =
SecondaryDefines[i].find(DefineName);
for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
llvm::StringMap<std::string>::iterator I =
SecondaryDefines[i].find(&DefineName[0],
&DefineName[0]+DefineName.size());
if (I == SecondaryDefines[i].end()) {
// Secondary target doesn't have this #define.
isPortable = false;
} else {
// Secondary target has this define, remember if it disagrees.
if (isPortable)
isPortable = I->second == DefineValue;
isPortable = I->getValue() == DefineValue;
// Remove it from the secondary target unconditionally.
SecondaryDefines[i].erase(I);
}
@ -133,25 +142,31 @@ void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
// Now that all of the primary target's defines have been handled and removed
// from the secondary target's define sets, go through the remaining secondary
// target's #defines and taint them.
for (unsigned i = 0, e = SecondaryDefines.size(); i != e; ++i) {
std::map<std::string, std::string> &Defs = SecondaryDefines[i];
for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
llvm::StringMap<std::string> &Defs = SecondaryDefines[i];
while (!Defs.empty()) {
const std::string &DefName = Defs.begin()->first;
const char *DefStart = Defs.begin()->getKeyData();
const char *DefEnd = DefStart + Defs.begin()->getKeyLength();
// Insert "#define_other_target defname".
const char *Command = "#define_other_target ";
Buffer.insert(Buffer.end(), Command, Command+strlen(Command));
Buffer.insert(Buffer.end(), DefName.begin(), DefName.end());
Buffer.insert(Buffer.end(), DefStart, DefEnd);
Buffer.push_back('\n');
// If any other secondary targets have this same define, remove it from
// them to avoid duplicate #define_other_target directives.
for (unsigned j = i+1; j != e; ++j)
SecondaryDefines[j].erase(DefName);
for (unsigned j = i+1; j != e; ++j) {
llvm::StringMap<std::string>::iterator I =
SecondaryDefines[j].find(DefStart, DefEnd);
if (I != SecondaryDefines[j].end())
SecondaryDefines[j].erase(I);
}
Defs.erase(Defs.begin());
}
}
delete[] SecondaryDefines;
}
/// ComputeWCharWidth - Determine the width of the wchar_t type for the primary
@ -185,9 +200,12 @@ void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
// Start by computing a mapping from the primary target's builtins to their
// info records for efficient lookup.
std::map<std::string, const Builtin::Info*> PrimaryRecs;
for (unsigned i = 0, e = NumRecords; i != e; ++i)
PrimaryRecs[Records[i].Name] = Records+i;
llvm::StringMap<const Builtin::Info*> PrimaryRecs;
for (unsigned i = 0, e = NumRecords; i != e; ++i) {
const char *BIName = Records[i].Name;
PrimaryRecs.GetOrCreateValue(BIName, BIName+strlen(BIName)).getValue()
= Records+i;
}
for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) {
// Get the builtins for this secondary target.
@ -202,7 +220,11 @@ void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
BuiltinNames2nd.insert(Records2nd[j].Name);
// Check to see if the primary target has this builtin.
if (const Builtin::Info *PrimBI = PrimaryRecs[Records2nd[j].Name]) {
llvm::StringMap<const Builtin::Info*>::iterator I =
PrimaryRecs.find(Records2nd[j].Name,
Records2nd[j].Name+strlen(Records2nd[j].Name));
if (I != PrimaryRecs.end()) {
const Builtin::Info *PrimBI = I->getValue();
// If does. If they are not identical, mark the builtin as being
// non-portable.
if (Records2nd[j] != *PrimBI)