diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3207,8 +3207,8 @@ " volatile bit-field width is dictated by the field container type. (ARM only).">>, Group; -def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group, - HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">; +def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group, + HelpText<"Generate code which only uses the general purpose registers (AArch64/x86 only)">; def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">, Group, HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -117,7 +117,20 @@ for (auto &F : CPUFeatures) setFeatureEnabled(Features, F, true); - if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec)) + std::vector UpdatedFeaturesVec; + for (const auto &Feature : FeaturesVec) { + // Expand general-regs-only to -x86, -mmx and -sse + if (Feature == "+general-regs-only") { + UpdatedFeaturesVec.push_back("-x87"); + UpdatedFeaturesVec.push_back("-mmx"); + UpdatedFeaturesVec.push_back("-sse"); + continue; + } + + UpdatedFeaturesVec.push_back(Feature); + } + + if (!TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec)) return false; // Can't do this earlier because we need to be able to explicitly enable @@ -126,20 +139,20 @@ // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled. auto I = Features.find("sse4.2"); if (I != Features.end() && I->getValue() && - llvm::find(FeaturesVec, "-popcnt") == FeaturesVec.end()) + llvm::find(UpdatedFeaturesVec, "-popcnt") == UpdatedFeaturesVec.end()) Features["popcnt"] = true; // Additionally, if SSE is enabled and mmx is not explicitly disabled, // then enable MMX. I = Features.find("sse"); if (I != Features.end() && I->getValue() && - llvm::find(FeaturesVec, "-mmx") == FeaturesVec.end()) + llvm::find(UpdatedFeaturesVec, "-mmx") == UpdatedFeaturesVec.end()) Features["mmx"] = true; // Enable xsave if avx is enabled and xsave is not explicitly disabled. I = Features.find("avx"); if (I != Features.end() && I->getValue() && - llvm::find(FeaturesVec, "-xsave") == FeaturesVec.end()) + llvm::find(UpdatedFeaturesVec, "-xsave") == UpdatedFeaturesVec.end()) Features["xsave"] = true; return true; @@ -866,6 +879,7 @@ .Case("fma4", true) .Case("fsgsbase", true) .Case("fxsr", true) + .Case("general-regs-only", true) .Case("gfni", true) .Case("hreset", true) .Case("invpcid", true) diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -213,5 +213,24 @@ // Now add any that the user explicitly requested on the command line, // which may override the defaults. - handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group); + for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group, + options::OPT_mgeneral_regs_only)) { + StringRef Name = A->getOption().getName(); + A->claim(); + + // Skip over "-m". + assert(Name.startswith("m") && "Invalid feature name."); + Name = Name.substr(1); + + // Replace -mgeneral-regs-only with -x87, -mmx, -sse + if (A->getOption().getID() == options::OPT_mgeneral_regs_only) { + Features.insert(Features.end(), {"-x87", "-mmx", "-sse"}); + continue; + } + + bool IsNegative = Name.startswith("no-"); + if (IsNegative) + Name = Name.substr(3); + Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); + } } diff --git a/clang/test/CodeGen/attr-target-general-regs-only-x86.c b/clang/test/CodeGen/attr-target-general-regs-only-x86.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-target-general-regs-only-x86.c @@ -0,0 +1,14 @@ +// Test general-regs-only target attribute on x86 + +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s + +// CHECK: define{{.*}} void @f() [[GPR_ATTRS:#[0-9]+]] +void __attribute__((target("general-regs-only"))) f() { } +// CHECK: define{{.*}} void @f_before() [[GPR_ATTRS:#[0-9]+]] +void __attribute__((target("avx2,general-regs-only"))) f_before() { } +// CHECK: define{{.*}} void @f_after() [[AVX2_ATTRS:#[0-9]+]] +void __attribute__((target("general-regs-only,avx2"))) f_after() { } + +// CHECK: attributes [[GPR_ATTRS]] = { {{.*}} "target-features"="{{.*}}-avx{{.*}}-avx2{{.*}}-avx512f{{.*}}-sse{{.*}}-sse2{{.*}}-ssse3{{.*}}-x87{{.*}}" +// CHECK: attributes [[AVX2_ATTRS]] = { {{.*}} "target-features"="{{.*}}+avx{{.*}}+avx2{{.*}}+sse{{.*}}+sse2{{.*}}+ssse3{{.*}}-avx512f{{.*}}-x87{{.*}}" diff --git a/clang/test/Driver/x86-mgeneral-regs-only.c b/clang/test/Driver/x86-mgeneral-regs-only.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/x86-mgeneral-regs-only.c @@ -0,0 +1,26 @@ +// Test the -mgeneral-regs-only option on x86 + +// RUN: %clang -target i386-unknown-linux-gnu -mgeneral-regs-only %s -### 2>&1 | FileCheck --check-prefix=CMD %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mgeneral-regs-only %s -### 2>&1 | FileCheck --check-prefix=CMD %s +// RUN: %clang -target i386-unknown-linux-gnu -mavx2 -mgeneral-regs-only %s -### 2>&1 | FileCheck --check-prefixes=CMD,CMD-BEFORE %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mavx2 -mgeneral-regs-only %s -### 2>&1 | FileCheck --check-prefixes=CMD,CMD-BEFORE %s +// RUN: %clang -target i386-unknown-linux-gnu -mgeneral-regs-only -mavx2 %s -### 2>&1 | FileCheck --check-prefixes=CMD,CMD-AFTER %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mgeneral-regs-only -mavx2 %s -### 2>&1 | FileCheck --check-prefixes=CMD,CMD-AFTER %s + +// RUN: %clang -target i386-unknown-linux-gnu -mgeneral-regs-only -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-GPR %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mgeneral-regs-only -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-GPR %s +// RUN: %clang -target i386-unknown-linux-gnu -mavx2 -mgeneral-regs-only -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-GPR %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mavx2 -mgeneral-regs-only -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-GPR %s +// RUN: %clang -target i386-unknown-linux-gnu -mgeneral-regs-only -mavx2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-AVX2 %s +// RUN: %clang -target x86_64-unknown-linux-gnu -mgeneral-regs-only -mavx2 -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=IR-AVX2 %s + +// CMD-BEFORE: "-target-feature" "+avx2" +// CMD: "-target-feature" "-x87" +// CMD: "-target-feature" "-mmx" +// CMD: "-target-feature" "-sse" +// CMD-AFTER: "-target-feature" "+avx2" + +void foo() { } + +// IR-GPR: attributes {{.*}} = { {{.*}} "target-features"="{{.*}}-avx{{.*}}-avx2{{.*}}-avx512f{{.*}}-sse{{.*}}-sse2{{.*}}-ssse3{{.*}}-x87{{.*}}" +// IR-AVX2: attributes {{.*}} = { {{.*}} "target-features"="{{.*}}+avx{{.*}}+avx2{{.*}}+sse{{.*}}+sse2{{.*}}+ssse3{{.*}}-avx512f{{.*}}-x87{{.*}}"