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