serge-sans-paille created this revision. serge-sans-paille added reviewers: aaron.ballman, nikic. Herald added subscribers: StephenFan, hiraditya. Herald added a project: All. serge-sans-paille requested review of this revision. Herald added subscribers: llvm-commits, cfe-commits, MaskRay. Herald added projects: clang, LLVM.
When used to find an exact match, some extra context can be used to totally cut some computations. This saves 1% of the instruction count when pre processing sqlite3.c through valgrind --tool=callgrind ./bin/clang -E sqlite3.c -o/dev/null Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D142026 Files: clang/lib/Driver/Driver.cpp llvm/include/llvm/Option/OptTable.h llvm/lib/Option/OptTable.cpp Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -227,12 +227,13 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude, unsigned FlagsToExclude, - unsigned MinimumLength) const { + unsigned MinimumLength, + unsigned MinimumDistance) const { assert(!Option.empty()); // Consider each [option prefix + option name] pair as a candidate, finding // the closest match. - unsigned BestDistance = UINT_MAX; + unsigned BestDistance = MinimumDistance + 1; SmallString<16> Candidate; SmallString<16> NormalizedName; @@ -276,6 +277,14 @@ // appropriate one. For example, if a user asks for "--helm", suggest // "--help" over "-help". for (auto CandidatePrefix : CandidateInfo.Prefixes) { + // If Candidate and NormalizedName have more than 'BestDistance' + // characters of difference, no need to compute the edit distance, it's + // going to be greater than BestDistance. Don't bother computing Candidate + // at all. + if (std::abs((signed)(CandidatePrefix.size() + CandidateName.size()) - + (signed)NormalizedName.size()) > (signed)BestDistance) { + continue; + } Candidate = CandidatePrefix; Candidate += CandidateName; unsigned Distance = StringRef(Candidate).edit_distance( Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -175,11 +175,21 @@ /// \param [in] MinimumLength - Don't find options shorter than this length. /// For example, a minimum length of 3 prevents "-x" from being considered /// near to "-S". + /// \param [in] MinimumDistance - Don't find options whose distance is greater + /// than this value. /// /// \return The edit distance of the nearest string found. unsigned findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0, - unsigned MinimumLength = 4) const; + unsigned MinimumLength = 4, + unsigned MinimumDistance = UINT_MAX - 1) const; + + bool findExact(StringRef Option, std::string &ExactString, + unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const { + return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, + Option.size(), 0) == 0; + } /// Parse a single argument; returning the new argument and /// updating Index. Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -313,8 +313,8 @@ std::string Nearest; if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) { - if (getOpts().findNearest(ArgString, Nearest, options::CC1Option) == 0 && - !IsCLMode()) { + if (!IsCLMode() && + getOpts().findExact(ArgString, Nearest, options::CC1Option)) { DiagID = diag::err_drv_unknown_argument_with_suggestion; Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest; } else { @@ -339,8 +339,8 @@ // Warn on joined arguments that are similar to a long argument. std::string ArgString = ArgStrings[A->getIndex()]; std::string Nearest; - if (getOpts().findNearest("-" + ArgString, Nearest, IncludedFlagsBitmask, - ExcludedFlagsBitmask) == 0) + if (getOpts().findExact("-" + ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask)) Diags.Report(diag::warn_drv_potentially_misspelled_joined_argument) << A->getAsString(Args) << Nearest; } @@ -2472,7 +2472,7 @@ getIncludeExcludeOptionFlagMasks(IsCLMode()); std::string Nearest; if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, - ExcludedFlagsBitmask) <= 1) { + ExcludedFlagsBitmask, 0, 1) <= 1) { Diag(clang::diag::err_drv_no_such_file_with_suggestion) << Value << Nearest; return false;
Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -227,12 +227,13 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude, unsigned FlagsToExclude, - unsigned MinimumLength) const { + unsigned MinimumLength, + unsigned MinimumDistance) const { assert(!Option.empty()); // Consider each [option prefix + option name] pair as a candidate, finding // the closest match. - unsigned BestDistance = UINT_MAX; + unsigned BestDistance = MinimumDistance + 1; SmallString<16> Candidate; SmallString<16> NormalizedName; @@ -276,6 +277,14 @@ // appropriate one. For example, if a user asks for "--helm", suggest // "--help" over "-help". for (auto CandidatePrefix : CandidateInfo.Prefixes) { + // If Candidate and NormalizedName have more than 'BestDistance' + // characters of difference, no need to compute the edit distance, it's + // going to be greater than BestDistance. Don't bother computing Candidate + // at all. + if (std::abs((signed)(CandidatePrefix.size() + CandidateName.size()) - + (signed)NormalizedName.size()) > (signed)BestDistance) { + continue; + } Candidate = CandidatePrefix; Candidate += CandidateName; unsigned Distance = StringRef(Candidate).edit_distance( Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -175,11 +175,21 @@ /// \param [in] MinimumLength - Don't find options shorter than this length. /// For example, a minimum length of 3 prevents "-x" from being considered /// near to "-S". + /// \param [in] MinimumDistance - Don't find options whose distance is greater + /// than this value. /// /// \return The edit distance of the nearest string found. unsigned findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0, - unsigned MinimumLength = 4) const; + unsigned MinimumLength = 4, + unsigned MinimumDistance = UINT_MAX - 1) const; + + bool findExact(StringRef Option, std::string &ExactString, + unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const { + return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, + Option.size(), 0) == 0; + } /// Parse a single argument; returning the new argument and /// updating Index. Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -313,8 +313,8 @@ std::string Nearest; if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) { - if (getOpts().findNearest(ArgString, Nearest, options::CC1Option) == 0 && - !IsCLMode()) { + if (!IsCLMode() && + getOpts().findExact(ArgString, Nearest, options::CC1Option)) { DiagID = diag::err_drv_unknown_argument_with_suggestion; Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest; } else { @@ -339,8 +339,8 @@ // Warn on joined arguments that are similar to a long argument. std::string ArgString = ArgStrings[A->getIndex()]; std::string Nearest; - if (getOpts().findNearest("-" + ArgString, Nearest, IncludedFlagsBitmask, - ExcludedFlagsBitmask) == 0) + if (getOpts().findExact("-" + ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask)) Diags.Report(diag::warn_drv_potentially_misspelled_joined_argument) << A->getAsString(Args) << Nearest; } @@ -2472,7 +2472,7 @@ getIncludeExcludeOptionFlagMasks(IsCLMode()); std::string Nearest; if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, - ExcludedFlagsBitmask) <= 1) { + ExcludedFlagsBitmask, 0, 1) <= 1) { Diag(clang::diag::err_drv_no_such_file_with_suggestion) << Value << Nearest; return false;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits