Skip to content

Commit 015ce0f

Browse files
committed
[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. llvm-svn: 243261
1 parent a96ffd5 commit 015ce0f

File tree

6 files changed

+145
-15
lines changed

6 files changed

+145
-15
lines changed

clang/include/clang/Driver/CLCompatOptions.td

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ def _SLASH_I : CLJoinedOrSeparate<"I">,
9292
def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
9393
Alias<funsigned_char>;
9494
def _SLASH_O0 : CLFlag<"O0">, Alias<O0>;
95-
def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">,
96-
MetaVarName<"<n>">, Alias<O>;
95+
def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">;
9796
def _SLASH_Ob0 : CLFlag<"Ob0">, HelpText<"Disable inlining">,
9897
Alias<fno_inline>;
9998
def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
@@ -105,8 +104,6 @@ def _SLASH_Os : CLFlag<"Os">, HelpText<"Optimize for size">, Alias<O>,
105104
AliasArgs<["s"]>;
106105
def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
107106
AliasArgs<["2"]>;
108-
def _SLASH_Ox : CLFlag<"Ox">, HelpText<"Maximum optimization">, Alias<O>,
109-
AliasArgs<["3"]>;
110107
def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">,
111108
Alias<fomit_frame_pointer>;
112109
def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">,
@@ -261,6 +258,7 @@ def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
261258
def _SLASH_nologo : CLIgnoredFlag<"nologo">;
262259
def _SLASH_Ob1 : CLIgnoredFlag<"Ob1">;
263260
def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
261+
def _SLASH_Og : CLIgnoredFlag<"Og">;
264262
def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
265263
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
266264
def _SLASH_sdl : CLIgnoredFlag<"sdl">;

clang/lib/Driver/MSVCToolChain.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,101 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
528528
Res |= SanitizerKind::Address;
529529
return Res;
530530
}
531+
532+
llvm::opt::DerivedArgList *
533+
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
534+
const char *BoundArch) const {
535+
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
536+
const OptTable &Opts = getDriver().getOpts();
537+
538+
// The -O[12xd] flag actually expands to several flags. We must desugar the
539+
// flags so that options embedded can be negated. For example, the '-O2' flag
540+
// enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
541+
// correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
542+
// aspect of '-O2'.
543+
//
544+
// Note that this expansion logic only applies to the *last* of '[12xd]'.
545+
546+
// First step is to search for the character we'd like to expand.
547+
const char *ExpandChar = nullptr;
548+
for (Arg *A : Args) {
549+
if (!A->getOption().matches(options::OPT__SLASH_O))
550+
continue;
551+
StringRef OptStr = A->getValue();
552+
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
553+
const char &OptChar = *(OptStr.data() + I);
554+
if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
555+
ExpandChar = OptStr.data() + I;
556+
}
557+
}
558+
559+
// The -O flag actually takes an amalgam of other options. For example,
560+
// '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
561+
for (Arg *A : Args) {
562+
if (!A->getOption().matches(options::OPT__SLASH_O)) {
563+
DAL->append(A);
564+
continue;
565+
}
566+
567+
StringRef OptStr = A->getValue();
568+
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
569+
const char &OptChar = *(OptStr.data() + I);
570+
switch (OptChar) {
571+
default:
572+
break;
573+
case '1':
574+
case '2':
575+
case 'x':
576+
case 'd':
577+
if (&OptChar == ExpandChar) {
578+
if (OptChar == 'd') {
579+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0));
580+
} else {
581+
if (OptChar == '1') {
582+
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
583+
} else if (OptChar == '2' || OptChar == 'x') {
584+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
585+
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
586+
}
587+
DAL->AddFlagArg(A,
588+
Opts.getOption(options::OPT_fomit_frame_pointer));
589+
if (OptChar == '1' || OptChar == '2')
590+
DAL->AddFlagArg(A,
591+
Opts.getOption(options::OPT_ffunction_sections));
592+
}
593+
}
594+
break;
595+
case 'b':
596+
if (isdigit(OptStr[I + 1]))
597+
++I;
598+
break;
599+
case 'g':
600+
break;
601+
case 'i':
602+
if (OptStr[I + 1] == '-') {
603+
++I;
604+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
605+
} else {
606+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
607+
}
608+
break;
609+
case 's':
610+
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
611+
break;
612+
case 't':
613+
DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
614+
break;
615+
case 'y':
616+
if (OptStr[I + 1] == '-') {
617+
++I;
618+
DAL->AddFlagArg(A,
619+
Opts.getOption(options::OPT_fno_omit_frame_pointer));
620+
} else {
621+
DAL->AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
622+
}
623+
break;
624+
}
625+
}
626+
}
627+
return DAL;
628+
}

clang/lib/Driver/ToolChains.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,10 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
811811
MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
812812
const llvm::opt::ArgList &Args);
813813

814+
llvm::opt::DerivedArgList *
815+
TranslateArgs(const llvm::opt::DerivedArgList &Args,
816+
const char *BoundArch) const override;
817+
814818
bool IsIntegratedAssemblerDefault() const override;
815819
bool IsUnwindTablesDefault() const override;
816820
bool isPICDefault() const override;

clang/lib/Driver/Tools.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8828,17 +8828,31 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
88288828
Args.AddAllArgs(CmdArgs, options::OPT_I);
88298829

88308830
// Optimization level.
8831+
if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
8832+
CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
8833+
: "/Oi-");
88318834
if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
88328835
if (A->getOption().getID() == options::OPT_O0) {
88338836
CmdArgs.push_back("/Od");
88348837
} else {
8838+
CmdArgs.push_back("/Og");
8839+
88358840
StringRef OptLevel = A->getValue();
8836-
if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
8837-
A->render(Args, CmdArgs);
8838-
else if (OptLevel == "3")
8839-
CmdArgs.push_back("/Ox");
8841+
if (OptLevel == "s" || OptLevel == "z")
8842+
CmdArgs.push_back("/Os");
8843+
else
8844+
CmdArgs.push_back("/Ot");
8845+
8846+
CmdArgs.push_back("/Ob2");
88408847
}
88418848
}
8849+
if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
8850+
options::OPT_fno_omit_frame_pointer))
8851+
CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
8852+
? "/Oy"
8853+
: "/Oy-");
8854+
if (!Args.hasArg(options::OPT_fwritable_strings))
8855+
CmdArgs.push_back("/GF");
88428856

88438857
// Flags for which clang-cl has an alias.
88448858
// FIXME: How can we ensure this stays in sync with relevant clang-cl options?

clang/test/Driver/cl-fallback.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
// CHECK: "-D" "foo=bar"
1515
// CHECK: "-U" "baz"
1616
// CHECK: "-I" "foo"
17-
// CHECK: "/Ox"
17+
// CHECK: "/Oi"
18+
// CHECK: "/Og"
19+
// CHECK: "/Ot"
20+
// CHECK: "/Ob2"
21+
// CHECK: "/Oy"
22+
// CHECK: "/GF"
1823
// CHECK: "/GR-"
1924
// CHECK: "/Gy-"
2025
// CHECK: "/Gw-"
@@ -38,16 +43,16 @@
3843
// O0: "/Od"
3944
// RUN: %clang_cl /fallback /O1 -### -- %s 2>&1 | FileCheck -check-prefix=O1 %s
4045
// O1: cl.exe
41-
// O1: "-O1"
46+
// O1: "/Og" "/Os" "/Ob2" "/Oy" "/GF" "/Gy"
4247
// RUN: %clang_cl /fallback /O2 -### -- %s 2>&1 | FileCheck -check-prefix=O2 %s
4348
// O2: cl.exe
44-
// O2: "-O2"
49+
// O2: "/Oi" "/Og" "/Ot" "/Ob2" "/Oy" "/GF" "/Gy"
4550
// RUN: %clang_cl /fallback /Os -### -- %s 2>&1 | FileCheck -check-prefix=Os %s
4651
// Os: cl.exe
47-
// Os: "-Os"
52+
// Os: "/Os"
4853
// RUN: %clang_cl /fallback /Ox -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s
4954
// Ox: cl.exe
50-
// Ox: "/Ox"
55+
// Ox: "/Oi" "/Og" "/Ot" "/Ob2" "/Oy" "/GF"
5156

5257
// Only fall back when actually compiling, not for e.g. /P (preprocess).
5358
// RUN: %clang_cl /fallback /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s

clang/test/Driver/cl-options.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
// J: -fno-signed-char
8282

8383
// RUN: %clang_cl /Ofoo -### -- %s 2>&1 | FileCheck -check-prefix=O %s
84-
// O: -Ofoo
84+
// O: /Ofoo
8585

8686
// RUN: %clang_cl /Ob0 -### -- %s 2>&1 | FileCheck -check-prefix=Ob0 %s
8787
// Ob0: -fno-inline
@@ -96,13 +96,24 @@
9696
// Oi_: -fno-builtin
9797

9898
// RUN: %clang_cl /Os -### -- %s 2>&1 | FileCheck -check-prefix=Os %s
99+
// Os-NOT: -mdisable-fp-elim
100+
// Os: -momit-leaf-frame-pointer
99101
// Os: -Os
100102

101103
// RUN: %clang_cl /Ot -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s
104+
// Ot-NOT: -mdisable-fp-elim
105+
// Ot: -momit-leaf-frame-pointer
102106
// Ot: -O2
103107

104108
// RUN: %clang_cl /Ox -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s
105-
// Ox: -O3
109+
// Ox-NOT: -mdisable-fp-elim
110+
// Ox: -momit-leaf-frame-pointer
111+
// Ox: -O2
112+
113+
// RUN: %clang_cl /O2sy- -### -- %s 2>&1 | FileCheck -check-prefix=PR24003 %s
114+
// PR24003: -mdisable-fp-elim
115+
// PR24003: -momit-leaf-frame-pointer
116+
// PR24003: -Os
106117

107118
// RUN: %clang_cl /Zs /Oy -- %s 2>&1
108119

0 commit comments

Comments
 (0)