[cfe-commits] r67564 - /cfe/trunk/lib/Driver/OptTable.cpp

Daniel Dunbar daniel at zuster.org
Mon Mar 23 14:50:40 PDT 2009


Author: ddunbar
Date: Mon Mar 23 16:50:40 2009
New Revision: 67564

URL: http://llvm.org/viewvc/llvm-project?rev=67564&view=rev
Log:
Driver: Make argument parsing fast.

On a synthetic command line consisting of almost all defined options,
this drops wall time from .00494 to .00336 and user time from .00258
to .00105.

On the same benchmark, clang-driver is about 15% faster than the
primary gcc driver and almost twice as fast as the gcc driver driver.

Modified:
    cfe/trunk/lib/Driver/OptTable.cpp

Modified: cfe/trunk/lib/Driver/OptTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/OptTable.cpp?rev=67564&r1=67563&r2=67564&view=diff

==============================================================================
--- cfe/trunk/lib/Driver/OptTable.cpp (original)
+++ cfe/trunk/lib/Driver/OptTable.cpp Mon Mar 23 16:50:40 2009
@@ -12,6 +12,7 @@
 #include "clang/Driver/Arg.h"
 #include "clang/Driver/ArgList.h"
 #include "clang/Driver/Option.h"
+#include <algorithm>
 #include <cassert>
 
 using namespace clang::driver;
@@ -199,6 +200,14 @@
   return Opt;
 }
 
+// Support lower_bound between info and an option name.
+static inline bool operator<(struct Info &I, const char *Name) {
+  return StrCmpOptionName(I.Name, Name) == -1;
+}
+static inline bool operator<(const char *Name, struct Info &I) {
+  return StrCmpOptionName(Name, I.Name) == -1;
+}
+
 Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
   unsigned Prev = Index;
   const char *Str = Args.getArgString(Index);
@@ -207,19 +216,29 @@
   if (Str[0] != '-' || Str[1] == '\0')
     return new PositionalArg(getOption(OPT_INPUT), Index++);
 
-  // FIXME: Make this fast.
-  for (unsigned j = FirstSearchableOption; j < LastOption; ++j) {
-    const char *OptName = getOptionName((options::ID) j);
-    
-    // Arguments are only accepted by options which prefix them.
-    if (memcmp(Str, OptName, strlen(OptName)) == 0) {
-      if (Arg *A = getOption((options::ID) j)->accept(Args, Index))
-        return A;
-
-      // Otherwise, see if this argument was missing values.
-      if (Prev != Index)
-        return 0;
-    }
+  struct Info *Start = OptionInfos + FirstSearchableOption - 1;
+  struct Info *End = OptionInfos + LastOption - 1;
+
+  // Find the first option which could be a prefix.
+  Start = std::lower_bound(Start, End, Str);
+
+  // Scan for first option which is a proper prefix.
+  for (; Start != End; ++Start)
+    if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0)
+      break;
+
+  // Look for a match until we don't have a prefix.
+  for (; Start != End; ++Start) {
+    if (memcmp(Start->Name, Str, strlen(Start->Name)) != 0)
+      break;
+
+    options::ID id = (options::ID) (Start - OptionInfos + 1);
+    if (Arg *A = getOption(id)->accept(Args, Index))
+      return A;
+
+    // Otherwise, see if this argument was missing values.
+    if (Prev != Index)
+      return 0;
   }
 
   return new PositionalArg(getOption(OPT_UNKNOWN), Index++);





More information about the cfe-commits mailing list