Index: cfe/trunk/include/clang/Driver/CLCompatOptions.td =================================================================== --- cfe/trunk/include/clang/Driver/CLCompatOptions.td +++ cfe/trunk/include/clang/Driver/CLCompatOptions.td @@ -138,6 +138,9 @@ // Non-aliases: +def _SLASH_arch : CLCompileJoined<"arch:">, + HelpText<"Set architecture for code generation">; + def _SLASH_M_Group : OptionGroup<"">, Group; def _SLASH_EH : CLJoined<"EH">, HelpText<"Exception handling model">; @@ -207,7 +210,6 @@ // Unsupported: def _SLASH_AI : CLJoined<"AI">; -def _SLASH_arch : CLJoined<"arch:">; def _SLASH_bigobj : CLFlag<"bigobj">; def _SLASH_clr : CLJoined<"clr">; def _SLASH_d2Zi_PLUS : CLFlag<"d2Zi+">; Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -1423,7 +1423,8 @@ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); } -static void getX86TargetFeatures(const llvm::Triple &Triple, +static void getX86TargetFeatures(const Driver & D, + const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { if (Triple.getArchName() == "x86_64h") { @@ -1446,6 +1447,31 @@ Features.push_back("+ssse3"); } + // Set features according to the -arch flag on MSVC + if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { + StringRef Arch = A->getValue(); + bool ArchUsed = false; + // First, look for flags that are shared in x86 and x86-64. + if (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::x86) { + if (Arch == "AVX" || Arch == "AVX2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + // Then, look for x86-specific flags. + if (Triple.getArch() == llvm::Triple::x86) { + if (Arch == "IA32") { + ArchUsed = true; + } else if (Arch == "SSE" || Arch == "SSE2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + if (!ArchUsed) + D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args); + } + // Now add any that the user explicitly requested on the command line, // which may override the defaults. for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group), @@ -1608,7 +1634,7 @@ break; case llvm::Triple::x86: case llvm::Triple::x86_64: - getX86TargetFeatures(Triple, Args, Features); + getX86TargetFeatures(D, Triple, Args, Features); break; } Index: cfe/trunk/test/Driver/cl-options.c =================================================================== --- cfe/trunk/test/Driver/cl-options.c +++ cfe/trunk/test/Driver/cl-options.c @@ -198,7 +198,6 @@ // (/Zs is for syntax-only) // RUN: %clang_cl /Zs \ // RUN: /AIfoo \ -// RUN: /arch:sse2 \ // RUN: /clr:pure \ // RUN: /docname \ // RUN: /d2Zi+ \ Index: cfe/trunk/test/Driver/cl-x86-flags.c =================================================================== --- cfe/trunk/test/Driver/cl-x86-flags.c +++ cfe/trunk/test/Driver/cl-x86-flags.c @@ -8,5 +8,76 @@ // RUN: -### -- 2>&1 %s | FileCheck -check-prefix=MFLAGS %s // MFLAGS-NOT: argument unused during compilation +// -arch:IA32 is no-op. +// RUN: %clang_cl -m32 -arch:IA32 -### -- 2>&1 %s | FileCheck -check-prefix=IA32 %s +// IA32-NOT: argument unused during compilation +// IA32-NOT: -target-feature + +// RUN: %clang_cl -m32 -arch:ia32 -### -- 2>&1 %s | FileCheck -check-prefix=ia32 %s +// ia32: argument unused during compilation +// ia32-NOT: -target-feature + +// RUN: %clang_cl -m64 -arch:IA32 -### -- 2>&1 %s | FileCheck -check-prefix=IA3264 %s +// IA3264: argument unused during compilation +// IA3264-NOT: -target-feature + +// RUN: %clang_cl -m32 -arch:SSE -### -- 2>&1 %s | FileCheck -check-prefix=SSE %s +// SSE: -target-feature +// SSE: +sse +// SSE-NOT: argument unused during compilation + +// RUN: %clang_cl -m32 -arch:sse -### -- 2>&1 %s | FileCheck -check-prefix=sse %s +// sse: argument unused during compilation +// sse-NOT: -target-feature + +// RUN: %clang_cl -m32 -arch:SSE2 -### -- 2>&1 %s | FileCheck -check-prefix=SSE2 %s +// SSE2: -target-feature +// SSE2: +sse2 +// SSE2-NOT: argument unused during compilation + +// RUN: %clang_cl -m32 -arch:sse2 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s +// sse2: argument unused during compilation +// sse2-NOT: -target-feature + +// RUN: %clang_cl -m64 -arch:SSE -### -- 2>&1 %s | FileCheck -check-prefix=SSE64 %s +// SSE64: argument unused during compilation +// SSE64-NOT: -target-feature + +// RUN: %clang_cl -m64 -arch:SSE2 -### -- 2>&1 %s | FileCheck -check-prefix=SSE264 %s +// SSE264: argument unused during compilation +// SSE264-NOT: -target-feature + +// RUN: %clang_cl -m32 -arch:AVX -### -- 2>&1 %s | FileCheck -check-prefix=AVX %s +// AVX: -target-feature +// AVX: +avx + +// RUN: %clang_cl -m32 -arch:avx -### -- 2>&1 %s | FileCheck -check-prefix=avx %s +// avx: argument unused during compilation +// avx-NOT: -target-feature + +// RUN: %clang_cl -m32 -arch:AVX2 -### -- 2>&1 %s | FileCheck -check-prefix=AVX2 %s +// AVX2: -target-feature +// AVX2: +avx2 + +// RUN: %clang_cl -m32 -arch:avx2 -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s +// avx2: argument unused during compilation +// avx2-NOT: -target-feature + +// RUN: %clang_cl -m64 -arch:AVX -### -- 2>&1 %s | FileCheck -check-prefix=AVX64 %s +// AVX64: -target-feature +// AVX64: +avx + +// RUN: %clang_cl -m64 -arch:avx -### -- 2>&1 %s | FileCheck -check-prefix=avx64 %s +// avx64: argument unused during compilation +// avx64-NOT: -target-feature + +// RUN: %clang_cl -m64 -arch:AVX2 -### -- 2>&1 %s | FileCheck -check-prefix=AVX264 %s +// AVX264: -target-feature +// AVX264: +avx2 + +// RUN: %clang_cl -m64 -arch:avx2 -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s +// avx264: argument unused during compilation +// avx264-NOT: -target-feature + void f() { }