[clang][LoongArch] Add support for LoongArch32 (#172619)

This patch adds support for LoongArch32, as introduced in
la-toolchain-conventions v1.2.

Co-authored-by: Sun Haiyong <sunhaiyong@zdbr.net>
Link:
https://github.com/loongson/la-toolchain-conventions/releases/tag/releases%2Fv1.2
Link:
https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703312.html
This commit is contained in:
hev 2026-01-17 16:27:54 +08:00 committed by GitHub
parent 7cbd8d509c
commit 0a9d480fad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 135 additions and 17 deletions

View File

@ -228,6 +228,13 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__loongarch_arch",
Twine('"') + ArchName + Twine('"'));
}
} else if (ArchName == "loongarch32") {
if (HasFeature32S)
Builder.defineMacro("__loongarch_arch",
Twine('"') + "la32v1.0" + Twine('"'));
else
Builder.defineMacro("__loongarch_arch",
Twine('"') + "la32rv1.0" + Twine('"'));
} else {
Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));
}
@ -268,6 +275,8 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
StringRef ABI = getABI();
if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
Builder.defineMacro("__loongarch_lp64");
else if (ABI == "ilp32d" || ABI == "ilp32f" || ABI == "ilp32s")
Builder.defineMacro("__loongarch_ilp32");
if (ABI == "lp64d" || ABI == "ilp32d") {
Builder.defineMacro("__loongarch_hard_float");
@ -356,6 +365,7 @@ bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {
.Case("loongarch64", Is64Bit)
.Case("32bit", !Is64Bit)
.Case("64bit", Is64Bit)
.Case("32s", HasFeature32S)
.Case("lsx", HasFeatureLSX)
.Case("lasx", HasFeatureLASX)
.Default(false);
@ -373,7 +383,9 @@ LoongArchTargetInfo::getTargetBuiltins() const {
bool LoongArchTargetInfo::handleTargetFeatures(
std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
for (const auto &Feature : Features) {
if (Feature == "+d" || Feature == "+f") {
if (Feature == "+32s") {
HasFeature32S = true;
} else if (Feature == "+d" || Feature == "+f") {
// "d" implies "f".
HasFeatureF = true;
if (Feature == "+d") {
@ -430,7 +442,7 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
switch (Kind) {
case AttrFeatureKind::Arch: {
if (llvm::LoongArch::isValidArchName(Value) || Value == "la64v1.0" ||
Value == "la64v1.1") {
Value == "la64v1.1" || Value == "la32v1.0" || Value == "la32rv1.0") {
std::vector<llvm::StringRef> ArchFeatures;
if (llvm::LoongArch::getArchFeatures(Value, ArchFeatures)) {
Ret.Features.insert(Ret.Features.end(), ArchFeatures.begin(),
@ -441,6 +453,8 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
Ret.Duplicate = "arch=";
else if (Value == "la64v1.0" || Value == "la64v1.1")
Ret.CPU = "loongarch64";
else if (Value == "la32v1.0" || Value == "la32rv1.0")
Ret.CPU = "loongarch32";
else
Ret.CPU = Value;
} else {

View File

@ -25,6 +25,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo {
protected:
std::string ABI;
std::string CPU;
bool HasFeature32S;
bool HasFeatureD;
bool HasFeatureF;
bool HasFeatureLSX;
@ -39,6 +40,7 @@ protected:
public:
LoongArchTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
HasFeature32S = false;
HasFeatureD = false;
HasFeatureF = false;
HasFeatureLSX = false;

View File

@ -299,7 +299,8 @@ std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args,
// If we have -march, use that.
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
Arch = A->getValue();
if (Arch == "la64v1.0" || Arch == "la64v1.1")
if (Arch == "la64v1.0" || Arch == "la64v1.1" || Arch == "la32v1.0" ||
Arch == "la32rv1.0")
CPU = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
else
CPU = Arch;

View File

@ -751,7 +751,12 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
break;
}
// TODO: handle loongarch32.
case llvm::Triple::loongarch32: {
StringRef ABIName =
loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());
CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));
break;
}
case llvm::Triple::loongarch64: {
StringRef ABIName =
loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());
@ -2369,6 +2374,12 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"i586-suse-linux", "i686-montavista-linux",
};
static const char *const LoongArch32LibDirs[] = {"/lib32", "/lib"};
static const char *const LoongArch32Triples[] = {
"loongarch32-linux-gnu", "loongarch32-unknown-linux-gnu",
"loongarch32-linux-gnuf32", "loongarch32-unknown-linux-gnuf32",
"loongarch32-linux-gnusf", "loongarch32-unknown-linux-gnusf"};
static const char *const LoongArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const LoongArch64Triples[] = {
"loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"};
@ -2639,7 +2650,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
}
break;
// TODO: Handle loongarch32.
case llvm::Triple::loongarch32:
LibDirs.append(begin(LoongArch32LibDirs), end(LoongArch32LibDirs));
TripleAliases.append(begin(LoongArch32Triples), end(LoongArch32Triples));
break;
case llvm::Triple::loongarch64:
LibDirs.append(begin(LoongArch64LibDirs), end(LoongArch64LibDirs));
TripleAliases.append(begin(LoongArch64Triples), end(LoongArch64Triples));

View File

@ -206,6 +206,19 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
if (Triple.getArch() == llvm::Triple::riscv32)
return "lib32";
if (Triple.getArch() == llvm::Triple::loongarch32) {
switch (Triple.getEnvironment()) {
default:
return "lib32";
case llvm::Triple::GNUSF:
case llvm::Triple::MuslSF:
return "lib32/sf";
case llvm::Triple::GNUF32:
case llvm::Triple::MuslF32:
return "lib32/f32";
}
}
return Triple.isArch32Bit() ? "lib" : "lib64";
}

View File

@ -0,0 +1,26 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
// RUN: %clang_cc1 -triple loongarch32 -emit-llvm %s -o - | FileCheck %s
__attribute__((target("arch=la32v1.0")))
// CHECK-LABEL: define dso_local void @testLa32v10(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void testLa32v10() {}
__attribute__((target("arch=la32rv1.0")))
// CHECK-LABEL: define dso_local void @testLa32rv10(
// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void testLa32rv10() {}
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch32" "target-features"="+32bit,+32s" }
// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch32" "target-features"="+32bit" }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
//.

View File

@ -1,3 +1,11 @@
// RUN: %clang --target=loongarch32 -march=la32v1.0 -fsyntax-only %s -### 2>&1 | \
// RUN: FileCheck %s --check-prefix=CC1-LA32V1P0
// RUN: %clang --target=loongarch32 -march=la32v1.0 -S -emit-llvm %s -o - | \
// RUN: FileCheck %s --check-prefix=IR-LA32V1P0
// RUN: %clang --target=loongarch32 -march=la32rv1.0 -fsyntax-only %s -### 2>&1 | \
// RUN: FileCheck %s --check-prefix=CC1-LA32RV1P0
// RUN: %clang --target=loongarch32 -march=la32rv1.0 -S -emit-llvm %s -o - | \
// RUN: FileCheck %s --check-prefix=IR-LA32RV1P0
// RUN: %clang --target=loongarch64 -march=loongarch64 -fsyntax-only %s -### 2>&1 | \
// RUN: FileCheck %s --check-prefix=CC1-LOONGARCH64
// RUN: %clang --target=loongarch64 -march=la464 -fsyntax-only %s -### 2>&1 | \
@ -19,6 +27,18 @@
// RUN: %clang --target=loongarch64 -march=la664 -S -emit-llvm %s -o - | \
// RUN: FileCheck %s --check-prefix=IR-LA664
// CC1-LA32V1P0: "-target-cpu" "loongarch32"
// CC1-LA32V1P0-NOT: "-target-feature"
// CC1-LA32V1P0: "-target-feature" "+32bit" "-target-feature" "+32s"
// CC1-LA32V1P0-NOT: "-target-feature"
// CC1-LA32V1P0: "-target-abi" "ilp32d"
// CC1-LA32RV1P0: "-target-cpu" "loongarch32"
// CC1-LA32RV1P0-NOT: "-target-feature"
// CC1-LA32RV1P0: "-target-feature" "+32bit"
// CC1-LA32RV1P0-NOT: "-target-feature"
// CC1-LA32RV1P0: "-target-abi" "ilp32d"
// CC1-LOONGARCH64: "-target-cpu" "loongarch64"
// CC1-LOONGARCH64-NOT: "-target-feature"
// CC1-LOONGARCH64: "-target-feature" "+relax" "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+ual"
@ -49,6 +69,9 @@
// CC1-LA664-NOT: "-target-feature"
// CC1-LA664: "-target-abi" "lp64d"
// IR-LA32V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch32" {{.*}}"target-features"="+32bit,+32s"
// IR-LA32RV1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch32" {{.*}}"target-features"="+32bit"
// IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+relax,+ual"
// IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+relax,+ual"
// IR-LA64V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+lsx,+relax,+ual"

View File

@ -1,3 +1,8 @@
// RUN: %clang --target=loongarch32 -mtune=loongarch32 -fsyntax-only %s -### 2>&1 | \
// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=loongarch32
// RUN: %clang --target=loongarch32 -mtune=loongarch32 -S -emit-llvm %s -o - | \
// RUN: FileCheck %s --check-prefix=IRATTR -DCPU=loongarch32
// 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 - | \

View File

@ -822,6 +822,12 @@
/// Check __loongarch_arch{_tune/_frecipe/_lam_bh/_lamcas/_ld_seq_sa/_div32/_scq}.
// RUN: %clang --target=loongarch32 -x c -E -dM %s -o - | \
// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la32rv1.0 -DTUNE=loongarch32 %s
// RUN: %clang --target=loongarch32 -x c -E -dM %s -o - -march=la32v1.0 | \
// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la32v1.0 -DTUNE=loongarch32 %s
// RUN: %clang --target=loongarch32 -x c -E -dM %s -o - -march=la32rv1.0 | \
// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la32rv1.0 -DTUNE=loongarch32 %s
// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - | \
// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 | \

View File

@ -2,6 +2,7 @@
#define LOONGARCH_FEATURE(NAME, KIND)
#endif
LOONGARCH_FEATURE("+32bit", FK_32BIT)
LOONGARCH_FEATURE("+64bit", FK_64BIT)
LOONGARCH_FEATURE("+f", FK_FP32)
LOONGARCH_FEATURE("+d", FK_FP64)
@ -16,6 +17,7 @@ LOONGARCH_FEATURE("+lamcas", FK_LAMCAS)
LOONGARCH_FEATURE("+ld-seq-sa", FK_LD_SEQ_SA)
LOONGARCH_FEATURE("+div32", FK_DIV32)
LOONGARCH_FEATURE("+scq", FK_SCQ)
LOONGARCH_FEATURE("+32s", FK_32S)
#undef LOONGARCH_FEATURE
@ -23,6 +25,7 @@ LOONGARCH_FEATURE("+scq", FK_SCQ)
#define LOONGARCH_ARCH(NAME, KIND, FEATURES)
#endif
LOONGARCH_ARCH("loongarch32", AK_LOONGARCH32, FK_32BIT)
LOONGARCH_ARCH("loongarch64", AK_LOONGARCH64, FK_64BIT | FK_FP32 | FK_FP64 | FK_UAL)
LOONGARCH_ARCH("la464", AK_LA464, FK_64BIT | FK_FP32 | FK_FP64 | FK_LSX | FK_LASX | FK_UAL)
LOONGARCH_ARCH("la664", AK_LA664, FK_64BIT | FK_FP32 | FK_FP64 | FK_LSX | FK_LASX | FK_UAL | FK_FRECIPE | FK_LAM_BH | FK_LAMCAS | FK_LD_SEQ_SA | FK_DIV32 | FK_SCQ)

View File

@ -24,6 +24,9 @@ class StringRef;
namespace LoongArch {
enum FeatureKind : uint32_t {
// 32-bit ISA is available.
FK_32BIT = 1 << 0,
// 64-bit ISA is available.
FK_64BIT = 1 << 1,
@ -67,6 +70,9 @@ enum FeatureKind : uint32_t {
// sc.q is available.
FK_SCQ = 1 << 14,
// 32-bit standard variant is available.
FK_32S = 1 << 15,
};
struct FeatureInfo {

View File

@ -171,6 +171,9 @@ def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit,
FeatureUAL,
FeatureExtLSX]>;
// Generic 32-bit processor.
def : ProcessorModel<"loongarch32", NoSchedModel, [Feature32Bit]>;
// Generic 64-bit processor with double-precision floating-point support.
def : ProcessorModel<"loongarch64", NoSchedModel, [Feature64Bit,
FeatureUAL,

View File

@ -26,18 +26,14 @@ namespace LoongArchABI {
static ABI checkABIStandardized(ABI Abi) {
StringRef ABIName;
switch (Abi) {
case ABI_ILP32S:
ABIName = "ilp32s";
break;
case ABI_ILP32F:
ABIName = "ilp32f";
break;
case ABI_ILP32D:
ABIName = "ilp32d";
break;
case ABI_LP64F:
ABIName = "lp64f";
break;
case ABI_ILP32S:
case ABI_ILP32D:
case ABI_LP64S:
case ABI_LP64D:
return Abi;

View File

@ -74,6 +74,13 @@ bool LoongArch::getArchFeatures(StringRef Arch,
return true;
}
if (Arch == "la32v1.0" || Arch == "la32rv1.0") {
Features.push_back("+32bit");
if (Arch == "la32v1.0")
Features.push_back("+32s");
return true;
}
return false;
}
@ -85,6 +92,5 @@ void LoongArch::fillValidCPUList(SmallVectorImpl<StringRef> &Values) {
}
StringRef LoongArch::getDefaultArch(bool Is64Bit) {
// TODO: use a real 32-bit arch name.
return Is64Bit ? "loongarch64" : "";
return Is64Bit ? "loongarch64" : "loongarch32";
}

View File

@ -1,12 +1,12 @@
; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32s < %s 2>&1 \
; RUN: | FileCheck %s -DABI=ilp32s --check-prefixes=CHECK,WARNING
; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32f < %s 2>&1 \
; RUN: | FileCheck %s -DABI=ilp32f --check-prefixes=CHECK,WARNING
; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32d < %s 2>&1 \
; RUN: | FileCheck %s -DABI=ilp32d --check-prefixes=CHECK,WARNING
; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64f < %s 2>&1 \
; RUN: | FileCheck %s -DABI=lp64f --check-prefixes=CHECK,WARNING
; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32s < %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK,NO-WARNING
; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32d < %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK,NO-WARNING
; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64s < %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK,NO-WARNING
; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64d < %s 2>&1 \