r243261 - [clang-cl] Handle -O correctly

David Majnemer david.majnemer at gmail.com
Mon Jul 27 00:32:11 PDT 2015


Author: majnemer
Date: Mon Jul 27 02:32:11 2015
New Revision: 243261

URL: http://llvm.org/viewvc/llvm-project?rev=243261&view=rev
Log:
[clang-cl] Handle -O correctly

We had multiple bugs here:
- We didn't support multiple optimization options in one argument.
  e.g. -O2y-
- We didn't correctly expand -O[12dx] to their respective options.
- We treated -O1 as clang -O1 instead of clang -Os.
- We treated -Ox as clang -O3 instead of clang -O2.  In fact, cl's -Ox
  option is *less* powerful than cl's -O2 option despite -Ox described
  as "Full Optimization".

This fixes PR24003.

Modified:
    cfe/trunk/include/clang/Driver/CLCompatOptions.td
    cfe/trunk/lib/Driver/MSVCToolChain.cpp
    cfe/trunk/lib/Driver/ToolChains.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/cl-fallback.c
    cfe/trunk/test/Driver/cl-options.c

Modified: cfe/trunk/include/clang/Driver/CLCompatOptions.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CLCompatOptions.td (original)
+++ cfe/trunk/include/clang/Driver/CLCompatOptions.td Mon Jul 27 02:32:11 2015
@@ -92,8 +92,7 @@ def _SLASH_I : CLJoinedOrSeparate<"I">,
 def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
   Alias<funsigned_char>;
 def _SLASH_O0 : CLFlag<"O0">, Alias<O0>;
-def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">,
-  MetaVarName<"<n>">, Alias<O>;
+def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">;
 def _SLASH_Ob0 : CLFlag<"Ob0">, HelpText<"Disable inlining">,
   Alias<fno_inline>;
 def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
@@ -105,8 +104,6 @@ def _SLASH_Os : CLFlag<"Os">, HelpText<"
   AliasArgs<["s"]>;
 def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
   AliasArgs<["2"]>;
-def _SLASH_Ox : CLFlag<"Ox">, HelpText<"Maximum optimization">, Alias<O>,
-  AliasArgs<["3"]>;
 def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">,
   Alias<fomit_frame_pointer>;
 def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">,
@@ -261,6 +258,7 @@ def _SLASH_kernel_ : CLIgnoredFlag<"kern
 def _SLASH_nologo : CLIgnoredFlag<"nologo">;
 def _SLASH_Ob1 : CLIgnoredFlag<"Ob1">;
 def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
+def _SLASH_Og : CLIgnoredFlag<"Og">;
 def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
 def _SLASH_RTC : CLIgnoredJoined<"RTC">;
 def _SLASH_sdl : CLIgnoredFlag<"sdl">;

Modified: cfe/trunk/lib/Driver/MSVCToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/MSVCToolChain.cpp?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/MSVCToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/MSVCToolChain.cpp Mon Jul 27 02:32:11 2015
@@ -528,3 +528,101 @@ SanitizerMask MSVCToolChain::getSupporte
   Res |= SanitizerKind::Address;
   return Res;
 }
+
+llvm::opt::DerivedArgList *
+MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+                             const char *BoundArch) const {
+  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+  const OptTable &Opts = getDriver().getOpts();
+
+  // The -O[12xd] flag actually expands to several flags.  We must desugar the
+  // flags so that options embedded can be negated.  For example, the '-O2' flag
+  // enables '-Oy'.  Expanding '-O2' into its constituent flags allows us to
+  // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
+  // aspect of '-O2'.
+  //
+  // Note that this expansion logic only applies to the *last* of '[12xd]'.
+
+  // First step is to search for the character we'd like to expand.
+  const char *ExpandChar = nullptr;
+  for (Arg *A : Args) {
+    if (!A->getOption().matches(options::OPT__SLASH_O))
+      continue;
+    StringRef OptStr = A->getValue();
+    for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+      const char &OptChar = *(OptStr.data() + I);
+      if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
+        ExpandChar = OptStr.data() + I;
+    }
+  }
+
+  // The -O flag actually takes an amalgam of other options.  For example,
+  // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
+  for (Arg *A : Args) {
+    if (!A->getOption().matches(options::OPT__SLASH_O)) {
+      DAL->append(A);
+      continue;
+    }
+
+    StringRef OptStr = A->getValue();
+    for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+      const char &OptChar = *(OptStr.data() + I);
+      switch (OptChar) {
+      default:
+        break;
+      case '1':
+      case '2':
+      case 'x':
+      case 'd':
+        if (&OptChar == ExpandChar) {
+          if (OptChar == 'd') {
+            DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0));
+          } else {
+            if (OptChar == '1') {
+              DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+            } else if (OptChar == '2' || OptChar == 'x') {
+              DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+              DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+            }
+            DAL->AddFlagArg(A,
+                            Opts.getOption(options::OPT_fomit_frame_pointer));
+            if (OptChar == '1' || OptChar == '2')
+              DAL->AddFlagArg(A,
+                              Opts.getOption(options::OPT_ffunction_sections));
+          }
+        }
+        break;
+      case 'b':
+        if (isdigit(OptStr[I + 1]))
+          ++I;
+        break;
+      case 'g':
+        break;
+      case 'i':
+        if (OptStr[I + 1] == '-') {
+          ++I;
+          DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
+        } else {
+          DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+        }
+        break;
+      case 's':
+        DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+        break;
+      case 't':
+        DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+        break;
+      case 'y':
+        if (OptStr[I + 1] == '-') {
+          ++I;
+          DAL->AddFlagArg(A,
+                          Opts.getOption(options::OPT_fno_omit_frame_pointer));
+        } else {
+          DAL->AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
+        }
+        break;
+      }
+    }
+  }
+  return DAL;
+}

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Mon Jul 27 02:32:11 2015
@@ -811,6 +811,10 @@ public:
   MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
                 const llvm::opt::ArgList &Args);
 
+  llvm::opt::DerivedArgList *
+  TranslateArgs(const llvm::opt::DerivedArgList &Args,
+                const char *BoundArch) const override;
+
   bool IsIntegratedAssemblerDefault() const override;
   bool IsUnwindTablesDefault() const override;
   bool isPICDefault() const override;

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Jul 27 02:32:11 2015
@@ -8828,17 +8828,31 @@ std::unique_ptr<Command> visualstudio::C
   Args.AddAllArgs(CmdArgs, options::OPT_I);
 
   // Optimization level.
+  if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
+    CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
+                                                                      : "/Oi-");
   if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
     if (A->getOption().getID() == options::OPT_O0) {
       CmdArgs.push_back("/Od");
     } else {
+      CmdArgs.push_back("/Og");
+
       StringRef OptLevel = A->getValue();
-      if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
-        A->render(Args, CmdArgs);
-      else if (OptLevel == "3")
-        CmdArgs.push_back("/Ox");
+      if (OptLevel == "s" || OptLevel == "z")
+        CmdArgs.push_back("/Os");
+      else
+        CmdArgs.push_back("/Ot");
+
+      CmdArgs.push_back("/Ob2");
     }
   }
+  if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
+                               options::OPT_fno_omit_frame_pointer))
+    CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
+                          ? "/Oy"
+                          : "/Oy-");
+  if (!Args.hasArg(options::OPT_fwritable_strings))
+    CmdArgs.push_back("/GF");
 
   // Flags for which clang-cl has an alias.
   // FIXME: How can we ensure this stays in sync with relevant clang-cl options?

Modified: cfe/trunk/test/Driver/cl-fallback.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-fallback.c?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-fallback.c (original)
+++ cfe/trunk/test/Driver/cl-fallback.c Mon Jul 27 02:32:11 2015
@@ -14,7 +14,12 @@
 // CHECK: "-D" "foo=bar"
 // CHECK: "-U" "baz"
 // CHECK: "-I" "foo"
-// CHECK: "/Ox"
+// CHECK: "/Oi"
+// CHECK: "/Og"
+// CHECK: "/Ot"
+// CHECK: "/Ob2"
+// CHECK: "/Oy"
+// CHECK: "/GF"
 // CHECK: "/GR-"
 // CHECK: "/Gy-"
 // CHECK: "/Gw-"
@@ -38,16 +43,16 @@
 // O0: "/Od"
 // RUN: %clang_cl /fallback /O1 -### -- %s 2>&1 | FileCheck -check-prefix=O1 %s
 // O1: cl.exe
-// O1: "-O1"
+// O1: "/Og" "/Os" "/Ob2" "/Oy" "/GF" "/Gy"
 // RUN: %clang_cl /fallback /O2 -### -- %s 2>&1 | FileCheck -check-prefix=O2 %s
 // O2: cl.exe
-// O2: "-O2"
+// O2: "/Oi" "/Og" "/Ot" "/Ob2" "/Oy" "/GF" "/Gy"
 // RUN: %clang_cl /fallback /Os -### -- %s 2>&1 | FileCheck -check-prefix=Os %s
 // Os: cl.exe
-// Os: "-Os"
+// Os: "/Os"
 // RUN: %clang_cl /fallback /Ox -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s
 // Ox: cl.exe
-// Ox: "/Ox"
+// Ox: "/Oi" "/Og" "/Ot" "/Ob2" "/Oy" "/GF"
 
 // Only fall back when actually compiling, not for e.g. /P (preprocess).
 // RUN: %clang_cl /fallback /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s

Modified: cfe/trunk/test/Driver/cl-options.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-options.c?rev=243261&r1=243260&r2=243261&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-options.c (original)
+++ cfe/trunk/test/Driver/cl-options.c Mon Jul 27 02:32:11 2015
@@ -81,7 +81,7 @@
 // J: -fno-signed-char
 
 // RUN: %clang_cl /Ofoo -### -- %s 2>&1 | FileCheck -check-prefix=O %s
-// O: -Ofoo
+// O: /Ofoo
 
 // RUN: %clang_cl /Ob0 -### -- %s 2>&1 | FileCheck -check-prefix=Ob0 %s
 // Ob0: -fno-inline
@@ -96,13 +96,24 @@
 // Oi_: -fno-builtin
 
 // RUN: %clang_cl /Os -### -- %s 2>&1 | FileCheck -check-prefix=Os %s
+// Os-NOT: -mdisable-fp-elim
+// Os: -momit-leaf-frame-pointer
 // Os: -Os
 
 // RUN: %clang_cl /Ot -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s
+// Ot-NOT: -mdisable-fp-elim
+// Ot: -momit-leaf-frame-pointer
 // Ot: -O2
 
 // RUN: %clang_cl /Ox -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s
-// Ox: -O3
+// Ox-NOT: -mdisable-fp-elim
+// Ox: -momit-leaf-frame-pointer
+// Ox: -O2
+
+// RUN: %clang_cl /O2sy- -### -- %s 2>&1 | FileCheck -check-prefix=PR24003 %s
+// PR24003: -mdisable-fp-elim
+// PR24003: -momit-leaf-frame-pointer
+// PR24003: -Os
 
 // RUN: %clang_cl /Zs /Oy -- %s 2>&1
 





More information about the cfe-commits mailing list