[clang][Preprocessor] Replace the slow translateFile call by a new, faster isMainFile check

The commit 3c28a2dc6b introduced the check that checks if we're
trying to re-enter a main file when building a preamble. Unfortunately this slowed down the preamble
compilation by 80-90% in some test cases, as translateFile is really slow. This change checks
to see if the FileEntry is the main file without calling translateFile, but by using the new
isMainFile check instead. This speeds up preamble building by 1.5-2x for certain test cases that we have.

rdar://59361291

Differential Revision: https://reviews.llvm.org/D79834
This commit is contained in:
Alex Lorenz 2020-05-14 14:11:31 -07:00
parent 428d0b6f77
commit 11d612ac99
4 changed files with 38 additions and 2 deletions

View File

@ -813,6 +813,11 @@ public:
MainFileID = FID;
}
/// Returns true when the given FileEntry corresponds to the main file.
///
/// The main file should be set prior to calling this function.
bool isMainFile(FileEntryRef SourceFile);
/// Set the file ID for the precompiled preamble.
void setPreambleFileID(FileID Preamble) {
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");

View File

@ -389,6 +389,14 @@ void SourceManager::clearIDTables() {
createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
}
bool SourceManager::isMainFile(FileEntryRef SourceFile) {
assert(MainFileID.isValid() && "expected initialized SourceManager");
auto FE = getFileEntryRefForID(MainFileID);
if (!FE)
return false;
return FE->getUID() == SourceFile.getUID();
}
void SourceManager::initializeForReplay(const SourceManager &Old) {
assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");

View File

@ -2054,8 +2054,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// some directives (e.g. #endif of a header guard) will never be seen.
// Since this will lead to confusing errors, avoid the inclusion.
if (Action == Enter && File && PreambleConditionalStack.isRecording() &&
SourceMgr.translateFile(&File->getFileEntry()) ==
SourceMgr.getMainFileID()) {
SourceMgr.isMainFile(*File)) {
Diag(FilenameTok.getLocation(),
diag::err_pp_including_mainfile_in_preamble);
return {ImportAction::None};

View File

@ -491,6 +491,30 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
}
TEST_F(SourceManagerTest, isMainFile) {
const char *Source = "int x;";
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(Source);
const FileEntry *SourceFile =
FileMgr.getVirtualFile("mainFile.cpp", Buf->getBufferSize(), 0);
SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
std::unique_ptr<llvm::MemoryBuffer> Buf2 =
llvm::MemoryBuffer::getMemBuffer(Source);
const FileEntry *SecondFile =
FileMgr.getVirtualFile("file2.cpp", Buf2->getBufferSize(), 0);
SourceMgr.overrideFileContents(SecondFile, std::move(Buf2));
FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
SourceMgr.setMainFileID(MainFileID);
EXPECT_TRUE(SourceMgr.isMainFile(FileEntryRef("mainFile.cpp", *SourceFile)));
EXPECT_TRUE(
SourceMgr.isMainFile(FileEntryRef("anotherName.cpp", *SourceFile)));
EXPECT_FALSE(SourceMgr.isMainFile(FileEntryRef("mainFile.cpp", *SecondFile)));
}
#endif
} // anonymous namespace