From 17ca3638e852ba81f389e9f896ed0420b52ae606 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 6 May 2009 21:07:50 +0000 Subject: [PATCH] More x86 target feature support. - Apologies for the extremely gross code duplication, I want to get this working and then decide how to get this information out of the back end. - This replaces -m[no-]sse4[12] by -m[no-]sse4, it appears gcc doesn't distinguish them? - -msse, etc. now properly disable/enable related features. - Don't always define __SSE3__... - The main missing functionality bit here is that we don't initialize the features based on the CPU for all -march options. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71117 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/TargetInfo.h | 12 ++++- include/clang/Driver/Options.def | 6 +-- lib/Basic/Targets.cpp | 62 +++++++++++++++++++++++-- test/Preprocessor/x86_target_features.c | 25 ++++++++++ tools/clang-cc/clang-cc.cpp | 12 ++--- 5 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 test/Preprocessor/x86_target_features.c diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index ce54db7581..f577d6b322 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -340,7 +340,17 @@ public: /// the \args CPU; this should include all legal feature strings on /// the target. virtual void getDefaultFeatures(const std::string &CPU, - llvm::StringMap &Features) { + llvm::StringMap &Features) const { + } + + /// setFeatureEnabled - Enable or disable a specific target feature, + /// the feature name must be valid. + /// + /// \return - False on error (invalid feature name). + virtual bool setFeatureEnabled(llvm::StringMap &Features, + const std::string &Name, + bool Enabled) const { + return false; } /// HandleTargetOptions - Perform initialization based on the user diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index cf077be969..31b32f8ebf 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -498,9 +498,8 @@ OPTION("-mno-red-zone", mno_red_zone, Flag, m_Group, INVALID, "", 0, 0, 0) OPTION("-mno-soft-float", mno_soft_float, Flag, m_Group, INVALID, "", 0, 0, 0) OPTION("-mno-sse2", mno_sse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mno-sse3", mno_sse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) -OPTION("-mno-sse41", mno_sse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) -OPTION("-mno-sse42", mno_sse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mno-sse4a", mno_sse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) +OPTION("-mno-sse4", mno_sse4, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mno-sse", mno_sse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mno-ssse3", mno_ssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mno-warn-nonportable-cfstrings", mno_warn_nonportable_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0) @@ -509,9 +508,8 @@ OPTION("-mred-zone", mred_zone, Flag, m_Group, INVALID, "", 0, 0, 0) OPTION("-msoft-float", msoft_float, Flag, m_Group, INVALID, "", 0, 0, 0) OPTION("-msse2", msse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-msse3", msse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) -OPTION("-msse41", msse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) -OPTION("-msse42", msse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-msse4a", msse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) +OPTION("-msse4", msse4, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-msse", msse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mssse3", mssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0) OPTION("-mtune=", mtune_EQ, Joined, m_Group, INVALID, "", 0, 0, 0) diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index d9ae003689..4e9c3a57a9 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -532,14 +532,16 @@ public: } virtual void getTargetDefines(const LangOptions &Opts, std::vector &Defines) const; - + virtual bool setFeatureEnabled(llvm::StringMap &Features, + const std::string &Name, + bool Enabled) const; virtual void getDefaultFeatures(const std::string &CPU, - llvm::StringMap &Features); + llvm::StringMap &Features) const; virtual void HandleTargetFeatures(const llvm::StringMap &Features); }; void X86TargetInfo::getDefaultFeatures(const std::string &CPU, - llvm::StringMap &Features) { + llvm::StringMap &Features) const { // FIXME: This should not be here. Features["3dnow"] = false; Features["3dnowa"] = false; @@ -572,6 +574,59 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, Features["sse2"] = Features["sse"] = Features["mmx"] = true; } +bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, + const std::string &Name, + bool Enabled) const { + // FIXME: This *really* should not be here. + if (!Features.count(Name) && Name != "sse4") + return false; + + if (Enabled) { + if (Name == "mmx") + Features["mmx"] = true; + else if (Name == "sse") + Features["mmx"] = Features["sse"] = true; + else if (Name == "sse2") + Features["mmx"] = Features["sse"] = Features["sse2"] = true; + else if (Name == "sse3") + Features["mmx"] = Features["sse"] = Features["sse2"] = + Features["sse3"] = true; + else if (Name == "ssse3") + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = true; + else if (Name == "sse4") + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; + else if (Name == "3dnow") + Features["3dnowa"] = true; + else if (Name == "3dnowa") + Features["3dnow"] = Features["3dnowa"] = true; + } else { + if (Name == "mmx") + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse") + Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse2") + Features["sse2"] = Features["sse3"] = Features["ssse3"] = + Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse3") + Features["sse3"] = Features["ssse3"] = Features["sse41"] = + Features["sse42"] = false; + else if (Name == "ssse3") + Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse4") + Features["sse41"] = Features["sse42"] = false; + else if (Name == "3dnow") + Features["3dnow"] = Features["3dnowa"] = false; + else if (Name == "3dnowa") + Features["3dnowa"] = false; + } + + return true; +} + /// HandleTargetOptions - Perform initialization based on the user /// configured set of features. void X86TargetInfo::HandleTargetFeatures(const llvm::StringMap&Features) { @@ -603,7 +658,6 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Define(Defs, "__amd64"); Define(Defs, "__x86_64"); Define(Defs, "__x86_64__"); - Define(Defs, "__SSE3__"); } else { DefineStd(Defs, "i386", Opts); } diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c new file mode 100644 index 0000000000..456c4fcf3a --- /dev/null +++ b/test/Preprocessor/x86_target_features.c @@ -0,0 +1,25 @@ +// FIXME: Use -triple, not -ccc-host-triple. + +// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -x c -E -dM -o %t %s && +// RUN: grep '#define __SSE2_MATH__ 1' %t && +// RUN: grep '#define __SSE2__ 1' %t && +// RUN: grep '#define __SSE3__ 1' %t && +// RUN: grep '#define __SSE4_1__ 1' %t && +// RUN: grep '#define __SSE4_2__ 1' %t && +// RUN: grep '#define __SSE_MATH__ 1' %t && +// RUN: grep '#define __SSE__ 1' %t && +// RUN: grep '#define __SSSE3__ 1' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -mno-sse2 -x c -E -dM -o %t %s && +// RUN: grep '#define __SSE2_MATH__ 1' %t | count 0 && +// RUN: grep '#define __SSE2__ 1' %t | count 0 && +// RUN: grep '#define __SSE3__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_1__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_2__ 1' %t | count 0 && +// RUN: grep '#define __SSE_MATH__ 1' %t && +// RUN: grep '#define __SSE__ 1' %t && +// RUN: grep '#define __SSSE3__ 1' %t | count 0 && + +// RUN: true + + diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index cdb606cb81..3282c193de 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -1426,17 +1426,11 @@ static void ComputeFeatureMap(TargetInfo *Target, Name); exit(1); } - - llvm::StringMap::iterator it = Features.find(Name + 1); - if (it == Features.end()) { - fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n", - Name); + if (!Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) { + fprintf(stderr, "error: clang-cc: invalid target feature name: %s\n", + Name + 1); exit(1); } - - // FIXME: Actually, we need to apply all the features implied by - // this feature. - it->second = (Name[0] == '+'); } } -- 2.40.0