diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -24,6 +24,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { protected: std::string ABI; + std::string CPU; bool HasFeatureD; bool HasFeatureF; @@ -40,6 +41,15 @@ WIntType = UnsignedInt; } + bool setCPU(const std::string &Name) override { + if (!isValidCPUName(Name)) + return false; + CPU = Name; + return true; + } + + StringRef getCPU() const { return CPU; } + StringRef getABI() const override { return ABI; } void getTargetDefines(const LangOptions &Opts, @@ -80,6 +90,9 @@ const std::vector &FeaturesVec) const override; bool hasFeature(StringRef Feature) const override; + + bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; }; class LLVM_LIBRARY_VISIBILITY LoongArch32TargetInfo diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -15,7 +15,7 @@ #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/TargetParser/TargetParser.h" +#include "llvm/TargetParser/LoongArchTargetParser.h" using namespace clang; using namespace clang::targets; @@ -198,7 +198,15 @@ else Builder.defineMacro("__loongarch_frlen", "0"); - // TODO: define __loongarch_arch and __loongarch_tune. + // Define __loongarch_arch. + StringRef ArchName = getCPU(); + Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"')); + + // Define __loongarch_tune. + StringRef TuneCPU = getTargetOpts().TuneCPU; + if (TuneCPU.empty()) + TuneCPU = ArchName; + Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"')); StringRef ABI = getABI(); if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s") @@ -270,3 +278,12 @@ } return true; } + +bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const { + return llvm::LoongArch::isValidCPUName(Name); +} + +void LoongArchTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + llvm::LoongArch::fillValidCPUList(Values); +} diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.h b/clang/lib/Driver/ToolChains/Arch/LoongArch.h --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.h +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.h @@ -23,6 +23,12 @@ StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); + +std::string postProcessTargetCPUString(const std::string &CPU, + const llvm::Triple &Triple); + +std::string getLoongArchTargetCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); } // end namespace loongarch } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "llvm/TargetParser/Host.h" #include "llvm/TargetParser/LoongArchTargetParser.h" using namespace clang::driver; @@ -126,23 +127,11 @@ const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { - StringRef ArchName; - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (!llvm::LoongArch::isValidArchName(A->getValue())) { - D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); - return; - } + std::string ArchName; + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) ArchName = A->getValue(); - } - - // TODO: handle -march=native and -mtune=xx. - - // Select a default arch name. - if (ArchName.empty() && Triple.isLoongArch64()) - ArchName = "loongarch64"; - - if (!ArchName.empty()) - llvm::LoongArch::getArchFeatures(ArchName, Features); + ArchName = postProcessTargetCPUString(ArchName, Triple); + llvm::LoongArch::getArchFeatures(ArchName, Features); // Select floating-point features determined by -mdouble-float, // -msingle-float, -msoft-float and -mfpu. @@ -187,3 +176,25 @@ if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ)) A->ignoreTargetSpecific(); } + +std::string loongarch::postProcessTargetCPUString(const std::string &CPU, + const llvm::Triple &Triple) { + std::string CPUString = CPU; + if (CPUString == "native") { + CPUString = llvm::sys::getHostCPUName(); + if (CPUString == "generic") + CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + } + if (CPUString.empty()) + CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + return CPUString; +} + +std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple) { + std::string CPU; + // If we have -march, use that. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + CPU = A->getValue(); + return postProcessTargetCPUString(CPU, Triple); +} diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -56,6 +56,7 @@ #include "llvm/Support/YAMLParser.h" #include "llvm/TargetParser/ARMTargetParserCommon.h" #include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/LoongArchTargetParser.h" #include "llvm/TargetParser/RISCVTargetParser.h" #include @@ -1852,10 +1853,20 @@ void Clang::AddLoongArchTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const llvm::Triple &Triple = getToolChain().getTriple(); + CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(loongarch::getLoongArchABI(getToolChain().getDriver(), Args, - getToolChain().getTriple()) - .data()); + CmdArgs.push_back( + loongarch::getLoongArchABI(getToolChain().getDriver(), Args, Triple) + .data()); + + // Handle -mtune. + if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { + std::string TuneCPU = A->getValue(); + TuneCPU = loongarch::postProcessTargetCPUString(TuneCPU, Triple); + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -474,6 +474,10 @@ case llvm::Triple::wasm32: case llvm::Triple::wasm64: return std::string(getWebAssemblyTargetCPU(Args)); + + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: + return loongarch::getLoongArchTargetCPU(Args, T); } } diff --git a/clang/test/Driver/loongarch-march-error.c b/clang/test/Driver/loongarch-march-error.c --- a/clang/test/Driver/loongarch-march-error.c +++ b/clang/test/Driver/loongarch-march-error.c @@ -1,7 +1,7 @@ // RUN: not %clang --target=loongarch64 -march=loongarch -fsyntax-only %s 2>&1 | \ -// RUN: FileCheck --check-prefix=LOONGARCH %s -// LOONGARCH: error: invalid arch name '-march=loongarch' - +// RUN: FileCheck -DCPU=loongarch %s // RUN: not %clang --target=loongarch64 -march=LA464 -fsyntax-only %s 2>&1 | \ -// RUN: FileCheck --check-prefix=LA464-UPPER %s -// LA464-UPPER: error: invalid arch name '-march=LA464' +// RUN: FileCheck -DCPU=LA464 %s + +// CHECK: error: unknown target CPU '[[CPU]]' +// CHECK-NEXT: note: valid target CPU values are: {{.*}} diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c --- a/clang/test/Driver/loongarch-march.c +++ b/clang/test/Driver/loongarch-march.c @@ -7,18 +7,20 @@ // RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-LA464 +// CC1-LOONGARCH64: "-target-cpu" "loongarch64" // CC1-LOONGARCH64-NOT: "-target-feature" // CC1-LOONGARCH64: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+ual" // CC1-LOONGARCH64-NOT: "-target-feature" // CC1-LOONGARCH64: "-target-abi" "lp64d" +// CC1-LA464: "-target-cpu" "la464" // CC1-LA464-NOT: "-target-feature" // CC1-LA464: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+lasx" "-target-feature" "+ual" // CC1-LA464-NOT: "-target-feature" // CC1-LA464: "-target-abi" "lp64d" -// IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-features"="+64bit,+d,+f,+ual" -// IR-LA464: attributes #[[#]] ={{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" +// IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+ual" +// IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-mtune.c b/clang/test/Driver/loongarch-mtune.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/loongarch-mtune.c @@ -0,0 +1,34 @@ +// RUN: %clang --target=loongarch64 -mtune=loongarch64 -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=loongarch64 +// RUN: %clang --target=loongarch64 -mtune=loongarch64 -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IRATTR -DCPU=loongarch64 + +// RUN: %clang --target=loongarch64 -mtune=la464 -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=la464 +// RUN: %clang --target=loongarch64 -mtune=la464 -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IRATTR -DCPU=la464 + +// RUN: %clang --target=loongarch64 -mtune=invalidcpu -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=invalidcpu +// RUN: not %clang --target=loongarch64 -mtune=invalidcpu -S -emit-llvm %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERROR -DCPU=invalidcpu + +// RUN: %clang --target=loongarch64 -mtune=generic -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=generic +// RUN: not %clang --target=loongarch64 -mtune=generic -S -emit-llvm %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERROR -DCPU=generic + +// RUN: %clang --target=loongarch64 -mtune=generic-la64 -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=generic-la64 +// RUN: not %clang --target=loongarch64 -mtune=generic-la64 -S -emit-llvm %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERROR -DCPU=generic-la64 + +// CC1ARG: "-tune-cpu" "[[CPU]]" +// IRATTR: "tune-cpu"="[[CPU]]" + +// ERROR: error: unknown target CPU '[[CPU]]' +// ERROR-NEXT: note: valid target CPU values are: {{.*}} + +int foo(void) { + return 3; +} diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c --- a/clang/test/Preprocessor/init-loongarch.c +++ b/clang/test/Preprocessor/init-loongarch.c @@ -787,3 +787,23 @@ // LA64-FPU0-LP64S: #define __loongarch_lp64 1 // LA64-FPU0-LP64S-NOT: #define __loongarch_single_float // LA64-FPU0-LP64S: #define __loongarch_soft_float 1 + +/// Check __loongarch_arch and __loongarch_tune. + +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=la464 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=loongarch64 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la464 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la464 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 -mtune=loongarch64 | \ +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=loongarch64 %s + +// ARCH-TUNE: #define __loongarch_arch "[[ARCH]]" +// ARCH-TUNE: #define __loongarch_tune "[[TUNE]]" diff --git a/llvm/include/llvm/TargetParser/LoongArchTargetParser.h b/llvm/include/llvm/TargetParser/LoongArchTargetParser.h --- a/llvm/include/llvm/TargetParser/LoongArchTargetParser.h +++ b/llvm/include/llvm/TargetParser/LoongArchTargetParser.h @@ -66,9 +66,12 @@ bool isValidArchName(StringRef Arch); bool getArchFeatures(StringRef Arch, std::vector &Features); +bool isValidCPUName(StringRef TuneCPU); +void fillValidCPUList(SmallVectorImpl &Values); +StringRef getDefaultArch(bool Is64Bit); } // namespace LoongArch } // namespace llvm -#endif // LLVM_SUPPORT_LOONGARCHTARGETPARSER_H +#endif // LLVM_TARGETPARSER_LOONGARCHTARGETPARSER_H diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td --- a/llvm/lib/Target/LoongArch/LoongArch.td +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -117,6 +117,11 @@ def : ProcessorModel<"generic-la32", NoSchedModel, [Feature32Bit]>; def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit, FeatureUAL]>; +// Generic 64-bit processor with double-precision floating-point support. +def : ProcessorModel<"loongarch64", NoSchedModel, [Feature64Bit, + FeatureUAL, + FeatureBasicD]>; + // Support generic for compatibility with other targets. The triple will be used // to change to the appropriate la32/la64 version. def : ProcessorModel<"generic", NoSchedModel, []>; diff --git a/llvm/lib/TargetParser/LoongArchTargetParser.cpp b/llvm/lib/TargetParser/LoongArchTargetParser.cpp --- a/llvm/lib/TargetParser/LoongArchTargetParser.cpp +++ b/llvm/lib/TargetParser/LoongArchTargetParser.cpp @@ -46,3 +46,15 @@ } return false; } + +bool LoongArch::isValidCPUName(StringRef Name) { return isValidArchName(Name); } + +void LoongArch::fillValidCPUList(SmallVectorImpl &Values) { + for (const auto A : AllArchs) + Values.emplace_back(A.Name); +} + +StringRef LoongArch::getDefaultArch(bool Is64Bit) { + // TODO: use a real 32-bit arch name. + return Is64Bit ? "loongarch64" : ""; +} diff --git a/llvm/test/CodeGen/LoongArch/cpus-invalid.ll b/llvm/test/CodeGen/LoongArch/cpus-invalid.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/cpus-invalid.ll @@ -0,0 +1,7 @@ +; RUN: llc < %s --mtriple=loongarch64 --mattr=+64bit --mcpu=invalidcpu 2>&1 | FileCheck %s + +; CHECK: {{.*}} is not a recognized processor for this target + +define void @f() { + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/cpus.ll b/llvm/test/CodeGen/LoongArch/cpus.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/cpus.ll @@ -0,0 +1,20 @@ +;; This tests that llc accepts all valid LoongArch CPUs. +;; Note the 'generic' names have been tested in cpu-name-generic.ll. + +; RUN: llc < %s --mtriple=loongarch64 --mcpu=loongarch64 2>&1 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 --mcpu=la464 2>&1 | FileCheck %s +; RUN: llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s + +; CHECK-NOT: {{.*}} is not a recognized processor for this target + +define void @f() { + ret void +} + +define void @tune_cpu_loongarch64() "tune-cpu"="loongarch64" { + ret void +} + +define void @tune_cpu_la464() "tune-cpu"="la464" { + ret void +}