diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d8655e52aa323..6bd5e0f8f196c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -135,6 +135,15 @@ Windows Support LoongArch Support ^^^^^^^^^^^^^^^^^ +- Patchable function entry (``-fpatchable-function-entry``) is now supported + on LoongArch. +- Unaligned memory accesses can be toggled by ``-m[no-]unaligned-access`` or the + aliases ``-m[no-]strict-align``. +- Non ``$``-prefixed GPR names (e.g. ``r4`` and ``a0``) are allowed in inlineasm + like GCC does. +- The ``-march=native`` ``-mtune=`` options and ``__loongarch_{arch,tune}`` + macros are now supported. + RISC-V Support ^^^^^^^^^^^^^^ diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index 6958479cd7c42..f08e5e732b035 100644 --- 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,19 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, else Builder.defineMacro("__loongarch_frlen", "0"); - // TODO: define __loongarch_arch and __loongarch_tune. + // Define __loongarch_arch. + StringRef Arch = llvm::LoongArch::getArch(); + if (Arch.empty()) + Arch = llvm::LoongArch::getDefaultArch(GRLen == 64); + if (!Arch.empty()) + Builder.defineMacro("__loongarch_arch", Arch); + + // Define __loongarch_tune. + StringRef TuneCPU = llvm::LoongArch::getTuneCPU(); + if (TuneCPU.empty()) + TuneCPU = Arch; + if (!TuneCPU.empty()) + Builder.defineMacro("__loongarch_tune", TuneCPU); StringRef ABI = getABI(); if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s") @@ -270,3 +282,12 @@ bool LoongArchTargetInfo::handleTargetFeatures( } return true; } + +bool LoongArchTargetInfo::isValidTuneCPUName(StringRef Name) const { + return llvm::LoongArch::isValidTuneCPUName(Name); +} + +void LoongArchTargetInfo::fillValidTuneCPUList( + SmallVectorImpl &Values) const { + llvm::LoongArch::fillValidTuneCPUList(Values); +} diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index 52c4ce4253689..60d545566b30f 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -80,6 +80,9 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { const std::vector &FeaturesVec) const override; bool hasFeature(StringRef Feature) const override; + + bool isValidTuneCPUName(StringRef Name) const override; + void fillValidTuneCPUList(SmallVectorImpl &Values) const override; }; class LLVM_LIBRARY_VISIBILITY LoongArch32TargetInfo diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index 856ad58f3bd9d..6cbb06b9a91f5 100644 --- 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; @@ -128,21 +129,29 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, std::vector &Features) { StringRef ArchName; if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (!llvm::LoongArch::isValidArchName(A->getValue())) { + ArchName = A->getValue(); + + // Handle -march=native. + if (ArchName == "native") { + ArchName = llvm::sys::getHostCPUName(); + if (ArchName == "generic") + ArchName = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + } + + if (!llvm::LoongArch::isValidArchName(ArchName)) { D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); return; } - 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()) + ArchName = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); - if (!ArchName.empty()) + if (!ArchName.empty()) { llvm::LoongArch::getArchFeatures(ArchName, Features); + llvm::LoongArch::setArch(ArchName); + } // Select floating-point features determined by -mdouble-float, // -msingle-float, -msoft-float and -mfpu. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index adb550d9c5da5..e3fa315ffcb1e 100644 --- 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 @@ -1853,10 +1854,25 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, 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)) { + StringRef TuneCPU = A->getValue(); + if (TuneCPU == "native") { + TuneCPU = llvm::sys::getHostCPUName(); + if (TuneCPU == "generic") + TuneCPU = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + } + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); + llvm::LoongArch::setTuneCPU(TuneCPU); + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, diff --git a/clang/test/Driver/loongarch-mtune-error.c b/clang/test/Driver/loongarch-mtune-error.c new file mode 100644 index 0000000000000..a029c3cbf5e11 --- /dev/null +++ b/clang/test/Driver/loongarch-mtune-error.c @@ -0,0 +1,6 @@ +// RUN: not %clang --target=loongarch64 -mtune=invalidcpu -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: not %clang --target=loongarch64 -mtune=generic -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: not %clang --target=loongarch64 -mtune=generic-la64 -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: error: unknown target CPU '{{.*}}' +// CHECK-NEXT: note: valid target CPU values are: {{.*}} diff --git a/clang/test/Driver/loongarch-mtune.c b/clang/test/Driver/loongarch-mtune.c new file mode 100644 index 0000000000000..a1d17ab4161a8 --- /dev/null +++ b/clang/test/Driver/loongarch-mtune.c @@ -0,0 +1,16 @@ +// 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 + +// CC1ARG: "-tune-cpu" "[[CPU]]" +// IRATTR: "tune-cpu"="[[CPU]]" + +int foo(void) { + return 3; +} diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c index 055431479f242..c3bc4d6b58dbd 100644 --- 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 index 2aa65ec070ec3..82ab064211d76 100644 --- a/llvm/include/llvm/TargetParser/LoongArchTargetParser.h +++ b/llvm/include/llvm/TargetParser/LoongArchTargetParser.h @@ -66,9 +66,16 @@ struct ArchInfo { bool isValidArchName(StringRef Arch); bool getArchFeatures(StringRef Arch, std::vector &Features); +bool isValidTuneCPUName(StringRef TuneCPU); +void fillValidTuneCPUList(SmallVectorImpl &Values); +StringRef getDefaultArch(bool Is64Bit); +void setArch(StringRef Arch); +StringRef getArch(); +void setTuneCPU(StringRef TuneCPU); +StringRef getTuneCPU(); } // 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 index 7241a5d63526f..0675caa3b6014 100644 --- a/llvm/lib/Target/LoongArch/LoongArch.td +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -117,6 +117,11 @@ include "LoongArchInstrInfo.td" 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 index 18b04600dbc66..72781513ff120 100644 --- a/llvm/lib/TargetParser/LoongArchTargetParser.cpp +++ b/llvm/lib/TargetParser/LoongArchTargetParser.cpp @@ -16,6 +16,9 @@ using namespace llvm; using namespace llvm::LoongArch; +StringRef Arch; +StringRef TuneCPU; + const FeatureInfo AllFeatures[] = { #define LOONGARCH_FEATURE(NAME, KIND) {NAME, KIND}, #include "llvm/TargetParser/LoongArchTargetParser.def" @@ -46,3 +49,25 @@ bool LoongArch::getArchFeatures(StringRef Arch, } return false; } + +bool LoongArch::isValidTuneCPUName(StringRef TuneCPU) { + return isValidArchName(TuneCPU); +} + +void LoongArch::fillValidTuneCPUList(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" : ""; +} + +void LoongArch::setArch(StringRef Name) { Arch = Name; } + +StringRef LoongArch::getArch() { return Arch; } + +void LoongArch::setTuneCPU(StringRef Name) { TuneCPU = Name; } + +StringRef LoongArch::getTuneCPU() { return TuneCPU; } diff --git a/llvm/test/CodeGen/LoongArch/cpus-invalid.ll b/llvm/test/CodeGen/LoongArch/cpus-invalid.ll new file mode 100644 index 0000000000000..b5435fb905006 --- /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 index 0000000000000..35945ae4de71f --- /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 +}