From bdecf07522a4d9654396f99862ab913768308ba0 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Tue, 4 Nov 2025 22:05:12 +0800 Subject: [PATCH 1/3] [X86][clang-cl] Add CL option /arch Ref: https://learn.microsoft.com/en-us/cpp/build/reference/vlen?view=msvc-170 --- .../clang/Basic/DiagnosticDriverKinds.td | 3 ++ clang/include/clang/Driver/Options.td | 4 +++ clang/lib/Driver/ToolChains/Clang.cpp | 31 +++++++++++++++++++ clang/test/Driver/cl-x86-flags.c | 21 +++++++++++++ 4 files changed, 59 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 83980e3ac35b7..e657abb86d95f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -207,6 +207,9 @@ def err_drv_amdgpu_ieee_without_no_honor_nans : Error< "invalid argument '-mno-amdgpu-ieee' only allowed with relaxed NaN handling">; def err_drv_argument_not_allowed_with : Error< "invalid argument '%0' not allowed with '%1'">; +def warn_drv_argument_not_allowed_with : Warning< + "invalid argument '%0' not allowed with '%1'">, + InGroup; def err_drv_cannot_open_randomize_layout_seed_file : Error< "cannot read randomize layout seed file '%0'">; def err_drv_invalid_version_number : Error< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 11e81e032d5fc..e271444184e44 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9218,6 +9218,10 @@ def : CLFlag<"Qscatter-">, Alias, def _SLASH_arch : CLCompileJoined<"arch:">, HelpText<"Set architecture for code generation">; +def _SLASH_vlen : CLCompileJoined<"vlen">, + HelpText<"Set vector length for autovectorization and other optimizations">; +def _SLASH_vlen_default : CLFlag<"vlen">, + HelpText<"Set default vector length for autovectorization and other optimizations">; def _SLASH_M_Group : OptionGroup<"">, Group; def _SLASH_volatile_Group : OptionGroup<"">, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 30d3e5293a31b..add34c63d9c24 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8266,6 +8266,37 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, << "/kernel"; } + if (Args.hasArg(options::OPT__SLASH_vlen_default)) { + // Override /vlen= options. + for (const Arg *A : Args.filtered(options::OPT__SLASH_vlen)) + A->claim(); + // Nothing to do for AVX512F/AVX512. + } else if (const Arg *A = Args.getLastArg(options::OPT__SLASH_vlen)) { + StringRef VLen = A->getValue(); + llvm::SmallSet Arch512 = {"AVX512F", "AVX512"}; + llvm::SmallSet Arch256 = {"AVX", "AVX2"}; + + StringRef Arch = Args.getLastArgValue(options::OPT__SLASH_arch); + if (Arch != "") { + if (VLen == "=512") { + if (Arch512.contains(Arch.str())) + CmdArgs.push_back("-mprefer-vector-width=512"); + else + D.Diag(diag::warn_drv_argument_not_allowed_with) + << "/vlen=512" << std::string("/arch:").append(Arch); + } else if (VLen == "=256") { + if (Arch512.contains(Arch.str())) + CmdArgs.push_back("-mprefer-vector-width=256"); + else if (!Arch256.contains(Arch.str())) + D.Diag(diag::warn_drv_argument_not_allowed_with) + << "/vlen=256" << std::string("/arch:").append(Arch); + } else { + D.Diag(diag::warn_drv_unknown_argument_clang_cl) + << std::string("/vlen").append(VLen); + } + } + } + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); if (MostGeneralArg && BestCaseArg) diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c index 89526744c0a49..56cfcb420f4ad 100644 --- a/clang/test/Driver/cl-x86-flags.c +++ b/clang/test/Driver/cl-x86-flags.c @@ -133,6 +133,27 @@ // tune: "-target-cpu" "sandybridge" // tune-SAME: "-tune-cpu" "haswell" +// RUN: %clang_cl -m64 -arch:AVX512 -vlen=512 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=vlen512 %s +// vlen512: "-mprefer-vector-width=512" + +// RUN: %clang_cl -m64 -arch:AVX512 -vlen=256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=vlen256 %s +// vlen256: "-mprefer-vector-width=256" + +// RUN: %clang_cl -m64 -arch:AVX512 -vlen=512 -vlen --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=noprefer %s +// noprefer-NOT: -mprefer-vector-width + +// RUN: %clang_cl -m64 -arch:AVX2 -vlen=512 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx2vlen512 %s +// avx2vlen512: invalid argument '/vlen=512' not allowed with '/arch:AVX2' + +// RUN: %clang_cl -m64 -arch:AVX2 -vlen=256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx2vlen256 %s +// avx2vlen256-NOT: invalid argument + +// RUN: %clang_cl -m32 -arch:SSE2 -vlen=256 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse2vlen256 %s +// sse2vlen256: invalid argument '/vlen=256' not allowed with '/arch:SSE2' + +// RUN: %clang_cl -m64 -arch:AVX -vlen256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avxvlen256 %s +// avxvlen256: unknown argument ignored in clang-cl: '/vlen256' + void f(void) { } From 266f047da0bd23c1a001ba658b94a05b456ea656 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Fri, 7 Nov 2025 18:57:13 +0800 Subject: [PATCH 2/3] Address review comments --- clang/include/clang/Driver/Options.td | 8 +++-- clang/lib/Driver/ToolChains/Clang.cpp | 42 ++++++++++++--------------- clang/test/Driver/cl-x86-flags.c | 3 -- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e271444184e44..0a414c685eae6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9218,10 +9218,12 @@ def : CLFlag<"Qscatter-">, Alias, def _SLASH_arch : CLCompileJoined<"arch:">, HelpText<"Set architecture for code generation">; -def _SLASH_vlen : CLCompileJoined<"vlen">, - HelpText<"Set vector length for autovectorization and other optimizations">; -def _SLASH_vlen_default : CLFlag<"vlen">, +def _SLASH_vlen : CLFlag<"vlen">, HelpText<"Set default vector length for autovectorization and other optimizations">; +def _SLASH_vlen_EQ_256 : CLFlag<"vlen=256">, + HelpText<"Set vector length of 256 bits for autovectorization and other optimizations">; +def _SLASH_vlen_EQ_512 : CLFlag<"vlen=512">, + HelpText<"Set vector length of 512 bits for autovectorization and other optimizations">; def _SLASH_M_Group : OptionGroup<"">, Group; def _SLASH_volatile_Group : OptionGroup<"">, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index add34c63d9c24..1adddc2e4b8e6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8266,34 +8266,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, << "/kernel"; } - if (Args.hasArg(options::OPT__SLASH_vlen_default)) { - // Override /vlen= options. - for (const Arg *A : Args.filtered(options::OPT__SLASH_vlen)) - A->claim(); - // Nothing to do for AVX512F/AVX512. - } else if (const Arg *A = Args.getLastArg(options::OPT__SLASH_vlen)) { - StringRef VLen = A->getValue(); + if (const Arg *A = Args.getLastArg(options::OPT__SLASH_vlen, + options::OPT__SLASH_vlen_EQ_256, + options::OPT__SLASH_vlen_EQ_512)) { llvm::SmallSet Arch512 = {"AVX512F", "AVX512"}; llvm::SmallSet Arch256 = {"AVX", "AVX2"}; StringRef Arch = Args.getLastArgValue(options::OPT__SLASH_arch); - if (Arch != "") { - if (VLen == "=512") { - if (Arch512.contains(Arch.str())) - CmdArgs.push_back("-mprefer-vector-width=512"); - else - D.Diag(diag::warn_drv_argument_not_allowed_with) - << "/vlen=512" << std::string("/arch:").append(Arch); - } else if (VLen == "=256") { - if (Arch512.contains(Arch.str())) - CmdArgs.push_back("-mprefer-vector-width=256"); - else if (!Arch256.contains(Arch.str())) - D.Diag(diag::warn_drv_argument_not_allowed_with) - << "/vlen=256" << std::string("/arch:").append(Arch); - } else { - D.Diag(diag::warn_drv_unknown_argument_clang_cl) - << std::string("/vlen").append(VLen); - } + + if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_512)) { + if (Arch512.contains(Arch.str())) + CmdArgs.push_back("-mprefer-vector-width=512"); + else + D.Diag(diag::warn_drv_argument_not_allowed_with) + << "/vlen=512" << std::string("/arch:").append(Arch); + } + + if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_256)) { + if (Arch512.contains(Arch.str())) + CmdArgs.push_back("-mprefer-vector-width=256"); + else if (!Arch256.contains(Arch.str())) + D.Diag(diag::warn_drv_argument_not_allowed_with) + << "/vlen=256" << std::string("/arch:").append(Arch); } } diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c index 56cfcb420f4ad..9753f3cb3f46b 100644 --- a/clang/test/Driver/cl-x86-flags.c +++ b/clang/test/Driver/cl-x86-flags.c @@ -151,9 +151,6 @@ // RUN: %clang_cl -m32 -arch:SSE2 -vlen=256 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse2vlen256 %s // sse2vlen256: invalid argument '/vlen=256' not allowed with '/arch:SSE2' -// RUN: %clang_cl -m64 -arch:AVX -vlen256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avxvlen256 %s -// avxvlen256: unknown argument ignored in clang-cl: '/vlen256' - void f(void) { } From 83d24bd7da27c52ea9eb1e642879c4c7834ffe25 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Fri, 7 Nov 2025 22:24:26 +0800 Subject: [PATCH 3/3] Address review comment --- clang/lib/Driver/ToolChains/Clang.cpp | 13 ++++++------- clang/test/Driver/cl-x86-flags.c | 8 ++++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1adddc2e4b8e6..e20963ac288d8 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8269,13 +8269,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, if (const Arg *A = Args.getLastArg(options::OPT__SLASH_vlen, options::OPT__SLASH_vlen_EQ_256, options::OPT__SLASH_vlen_EQ_512)) { - llvm::SmallSet Arch512 = {"AVX512F", "AVX512"}; - llvm::SmallSet Arch256 = {"AVX", "AVX2"}; - - StringRef Arch = Args.getLastArgValue(options::OPT__SLASH_arch); + llvm::Triple::ArchType AT = getToolChain().getArch(); + StringRef Default = AT == llvm::Triple::x86 ? "IA32" : "SSE2"; + StringRef Arch = Args.getLastArgValue(options::OPT__SLASH_arch, Default); if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_512)) { - if (Arch512.contains(Arch.str())) + if (Arch == "AVX512F" || Arch == "AVX512") CmdArgs.push_back("-mprefer-vector-width=512"); else D.Diag(diag::warn_drv_argument_not_allowed_with) @@ -8283,9 +8282,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, } if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_256)) { - if (Arch512.contains(Arch.str())) + if (Arch == "AVX512F" || Arch == "AVX512") CmdArgs.push_back("-mprefer-vector-width=256"); - else if (!Arch256.contains(Arch.str())) + else if (Arch != "AVX" && Arch != "AVX2") D.Diag(diag::warn_drv_argument_not_allowed_with) << "/vlen=256" << std::string("/arch:").append(Arch); } diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c index 9753f3cb3f46b..4dae49aab7ac7 100644 --- a/clang/test/Driver/cl-x86-flags.c +++ b/clang/test/Driver/cl-x86-flags.c @@ -139,8 +139,8 @@ // RUN: %clang_cl -m64 -arch:AVX512 -vlen=256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=vlen256 %s // vlen256: "-mprefer-vector-width=256" -// RUN: %clang_cl -m64 -arch:AVX512 -vlen=512 -vlen --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=noprefer %s -// noprefer-NOT: -mprefer-vector-width +// RUN: %clang_cl -m64 -arch:AVX512 -vlen=512 -vlen --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=novlen %s +// novlen-NOT: -mprefer-vector-width // RUN: %clang_cl -m64 -arch:AVX2 -vlen=512 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx2vlen512 %s // avx2vlen512: invalid argument '/vlen=512' not allowed with '/arch:AVX2' @@ -149,8 +149,12 @@ // avx2vlen256-NOT: invalid argument // RUN: %clang_cl -m32 -arch:SSE2 -vlen=256 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse2vlen256 %s +// RUN: %clang_cl -m64 -vlen=256 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=sse2vlen256 %s // sse2vlen256: invalid argument '/vlen=256' not allowed with '/arch:SSE2' +// RUN: %clang_cl -m32 -vlen=256 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=ia32vlen256 %s +// ia32vlen256: invalid argument '/vlen=256' not allowed with '/arch:IA32' + void f(void) { }