From c3e0fb406fb6fe83566dc6d8b05362e0a2c1e191 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 8 Jul 2011 23:31:17 +0000 Subject: [PATCH] Change -mno-mmx to be more compatible with gcc. Specifically, -mno-mmx should not imply -mno-sse. Note that because we don't usually touch the MMX registers anyway, all -mno-mmx needs to do is tweak the x86-32 calling convention a little for vectors that look like MMX vectors, and prevent the definition of __MMX__. clang doesn't actually stop the user from using MMX inline asm operands or MMX builtins in -mno-mmx mode; as a QOI issue, it would be nice to diagnose, but I doubt it really matters much. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134770 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets.cpp | 90 +++++++++++++++----------- lib/CodeGen/TargetInfo.cpp | 24 ++++--- test/CodeGen/x86_32-arguments-darwin.c | 3 +- test/CodeGen/x86_32-arguments-linux.c | 2 +- test/CodeGen/x86_32-arguments-nommx.c | 11 ++++ test/Sema/x86-builtin-palignr.c | 4 +- 6 files changed, 84 insertions(+), 50 deletions(-) create mode 100644 test/CodeGen/x86_32-arguments-nommx.c diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index b98baaa938..33113d465c 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -1110,18 +1110,18 @@ const TargetInfo::AddlRegName AddlRegNames[] = { // most of the implementation can be shared. class X86TargetInfo : public TargetInfo { enum X86SSEEnum { - NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42 + NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42 } SSELevel; - enum AMD3DNowEnum { - NoAMD3DNow, AMD3DNow, AMD3DNowAthlon - } AMD3DNowLevel; + enum MMX3DNowEnum { + NoMMX3DNow, MMX, AMD3DNow, AMD3DNowAthlon + } MMX3DNowLevel; bool HasAES; bool HasAVX; public: X86TargetInfo(const std::string& triple) - : TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow), + : TargetInfo(triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), HasAES(false), HasAVX(false) { LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } @@ -1159,6 +1159,9 @@ public: virtual void getDefaultFeatures(const std::string &CPU, llvm::StringMap &Features) const; virtual void HandleTargetFeatures(std::vector &Features); + virtual const char* getABI() const { + return MMX3DNowLevel == NoMMX3DNow ? "no-mmx" : ""; + } }; void X86TargetInfo::getDefaultFeatures(const std::string &CPU, @@ -1190,23 +1193,31 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, ; else if (CPU == "pentium-mmx" || CPU == "pentium2") setFeatureEnabled(Features, "mmx", true); - else if (CPU == "pentium3") + else if (CPU == "pentium3") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse", true); - else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64") + } else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse2", true); - else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona") + } else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse3", true); - else if (CPU == "core2") + } else if (CPU == "core2") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "ssse3", true); - else if (CPU == "penryn") { + } else if (CPU == "penryn") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); Features["sse42"] = false; - } else if (CPU == "atom") + } else if (CPU == "atom") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse3", true); - else if (CPU == "corei7") { + } else if (CPU == "corei7") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); setFeatureEnabled(Features, "aes", true); } else if (CPU == "corei7-avx") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse4", true); setFeatureEnabled(Features, "aes", true); // setFeatureEnabled(Features, "avx", true); @@ -1214,7 +1225,6 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, setFeatureEnabled(Features, "mmx", true); else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") { - setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "3dnow", true); } else if (CPU == "athlon-4" || CPU == "athlon-xp" || CPU == "athlon-mp") { setFeatureEnabled(Features, "sse", true); @@ -1226,8 +1236,10 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, } else if (CPU == "k8-sse3") { setFeatureEnabled(Features, "sse3", true); setFeatureEnabled(Features, "3dnowa", true); - } else if (CPU == "c3-2") + } else if (CPU == "c3-2") { + setFeatureEnabled(Features, "mmx", true); setFeatureEnabled(Features, "sse", true); + } } bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, @@ -1243,34 +1255,31 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap &Features, if (Name == "mmx") Features["mmx"] = true; else if (Name == "sse") - Features["mmx"] = Features["sse"] = true; + Features["sse"] = true; else if (Name == "sse2") - Features["mmx"] = Features["sse"] = Features["sse2"] = true; + Features["sse"] = Features["sse2"] = true; else if (Name == "sse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = - Features["sse3"] = true; + Features["sse"] = Features["sse2"] = Features["sse3"] = true; else if (Name == "ssse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = true; else if (Name == "sse4" || Name == "sse4.2") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; else if (Name == "sse4.1") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = true; else if (Name == "3dnow") - Features["3dnowa"] = true; + Features["mmx"] = Features["3dnow"] = true; else if (Name == "3dnowa") - Features["3dnow"] = Features["3dnowa"] = true; + Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = true; else if (Name == "aes") Features["aes"] = true; else if (Name == "avx") Features["avx"] = true; } else { if (Name == "mmx") - Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = - Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; + Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = false; else if (Name == "sse") Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; @@ -1328,18 +1337,25 @@ void X86TargetInfo::HandleTargetFeatures(std::vector &Features) { .Case("sse3", SSE3) .Case("sse2", SSE2) .Case("sse", SSE1) - .Case("mmx", MMX) - .Default(NoMMXSSE); + .Default(NoSSE); SSELevel = std::max(SSELevel, Level); - AMD3DNowEnum ThreeDNowLevel = - llvm::StringSwitch(Features[i].substr(1)) + MMX3DNowEnum ThreeDNowLevel = + llvm::StringSwitch(Features[i].substr(1)) .Case("3dnowa", AMD3DNowAthlon) .Case("3dnow", AMD3DNow) - .Default(NoAMD3DNow); + .Case("mmx", MMX) + .Default(NoMMX3DNow); - AMD3DNowLevel = std::max(AMD3DNowLevel, ThreeDNowLevel); + MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel); } + + // Don't tell the backend if we're turning off mmx; it will end up disabling + // SSE, which we don't want. + std::vector::iterator it; + it = std::find(Features.begin(), Features.end(), "-mmx"); + if (it != Features.end()) + Features.erase(it); } /// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines @@ -1394,9 +1410,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case SSE1: Builder.defineMacro("__SSE__"); Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied. - case MMX: - Builder.defineMacro("__MMX__"); - case NoMMXSSE: + case NoSSE: break; } @@ -1418,12 +1432,14 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, } // Each case falls through to the previous one here. - switch (AMD3DNowLevel) { + switch (MMX3DNowLevel) { case AMD3DNowAthlon: Builder.defineMacro("__3dNOW_A__"); case AMD3DNow: Builder.defineMacro("__3dNOW__"); - case NoAMD3DNow: + case MMX: + Builder.defineMacro("__MMX__"); + case NoMMX3DNow: break; } } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 8736d59f56..28afda1d66 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -374,6 +374,7 @@ class X86_32ABIInfo : public ABIInfo { bool IsDarwinVectorABI; bool IsSmallStructInRegABI; + bool IsMMXDisabled; static bool isRegisterSize(unsigned Size) { return (Size == 8 || Size == 16 || Size == 32 || Size == 64); @@ -403,14 +404,15 @@ public: virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; - X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p) - : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p) {} + X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m) + : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p), + IsMMXDisabled(m) {} }; class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { public: - X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p) - :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p)) {} + X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m) + :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, m)) {} void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; @@ -701,6 +703,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const { const llvm::Type *IRType = CGT.ConvertTypeRecursive(Ty); if (UseX86_MMXType(IRType)) { + if (IsMMXDisabled) + return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), + 64)); ABIArgInfo AAI = ABIArgInfo::getDirect(IRType); AAI.setCoerceToType(llvm::Type::getX86_MMXTy(getVMContext())); return AAI; @@ -3006,10 +3011,12 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::msp430: return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types)); - case llvm::Triple::x86: + case llvm::Triple::x86: { + bool DisableMMX = strcmp(getContext().Target.getABI(), "no-mmx") == 0; + if (Triple.isOSDarwin()) return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, true, true)); + new X86_32TargetCodeGenInfo(Types, true, true, DisableMMX)); switch (Triple.getOS()) { case llvm::Triple::Cygwin: @@ -3020,12 +3027,13 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::OpenBSD: case llvm::Triple::NetBSD: return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, false, true)); + new X86_32TargetCodeGenInfo(Types, false, true, DisableMMX)); default: return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, false, false)); + new X86_32TargetCodeGenInfo(Types, false, false, DisableMMX)); } + } case llvm::Triple::x86_64: switch (Triple.getOS()) { diff --git a/test/CodeGen/x86_32-arguments-darwin.c b/test/CodeGen/x86_32-arguments-darwin.c index f7e2a5368d..83f0f648a2 100644 --- a/test/CodeGen/x86_32-arguments-darwin.c +++ b/test/CodeGen/x86_32-arguments-darwin.c @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -w -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s -// RUN: FileCheck < %t %s +// RUN: %clang_cc1 -w -fblocks -triple i386-apple-darwin9 -target-cpu yonah -emit-llvm -o - %s | FileCheck %s // CHECK: define signext i8 @f0() char f0(void) { diff --git a/test/CodeGen/x86_32-arguments-linux.c b/test/CodeGen/x86_32-arguments-linux.c index 2f246f85b5..81dcaf6af5 100644 --- a/test/CodeGen/x86_32-arguments-linux.c +++ b/test/CodeGen/x86_32-arguments-linux.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -w -fblocks -triple i386-pc-linux-gnu -emit-llvm -o %t %s +// RUN: %clang_cc1 -w -fblocks -triple i386-pc-linux-gnu -target-cpu pentium4 -emit-llvm -o %t %s // RUN: FileCheck < %t %s // CHECK: define void @f56( diff --git a/test/CodeGen/x86_32-arguments-nommx.c b/test/CodeGen/x86_32-arguments-nommx.c new file mode 100644 index 0000000000..d503ed0ad8 --- /dev/null +++ b/test/CodeGen/x86_32-arguments-nommx.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -target-feature -mmx -target-feature +sse2 -triple i686-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s + +// no-mmx should put mmx into memory +typedef int __attribute__((vector_size (8))) i32v2; +int a(i32v2 x) { return x[0]; } +// CHECK: define i32 @a(i64 %x.coerce) + +// but SSE2 vectors should still go into an SSE2 register +typedef int __attribute__((vector_size (16))) i32v4; +int b(i32v4 x) { return x[0]; } +// CHECK: define i32 @b(<4 x i32> %x.coerce) diff --git a/test/Sema/x86-builtin-palignr.c b/test/Sema/x86-builtin-palignr.c index 83719a379f..6e1303c8a1 100644 --- a/test/Sema/x86-builtin-palignr.c +++ b/test/Sema/x86-builtin-palignr.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -ffreestanding -fsyntax-only -target-feature +ssse3 -verify -triple x86_64-pc-linux-gnu %s -// RUN: %clang_cc1 -ffreestanding -fsyntax-only -target-feature +ssse3 -verify -triple i686-apple-darwin10 %s +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -target-feature +ssse3 -target-feature +mmx -verify -triple x86_64-pc-linux-gnu %s +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -target-feature +ssse3 -target-feature +mmx -verify -triple i686-apple-darwin10 %s #include -- 2.40.0