[llvm] 695c81e - [LoongArch] Implement handling of triple-implied ABIs
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 1 19:39:10 PST 2023
Author: WANG Xuerui
Date: 2023-02-02T11:34:01+08:00
New Revision: 695c81e8a61a784f881255ea62a3ea76c1e2ee51
URL: https://github.com/llvm/llvm-project/commit/695c81e8a61a784f881255ea62a3ea76c1e2ee51
DIFF: https://github.com/llvm/llvm-project/commit/695c81e8a61a784f881255ea62a3ea76c1e2ee51.diff
LOG: [LoongArch] Implement handling of triple-implied ABIs
According to the [[ https://loongson.github.io/LoongArch-Documentation/LoongArch-toolchain-conventions-EN.html | LoongArch Toolchain Conventions ]]
it is possible to specify the ABI modifier (the "D" part of "LP64D")
via the environment field in the target triple. This is needed for
proper support for Debian-style multiarch tuples as well, so add triple
awareness to `LoongArchSubtarget` via addition of
`LoongArchABI::computeTargetABI`. Let the explicit `--target-abi`
argument intuitively take precedence over the triple-implied ABI.
Reviewed By: SixWeining
Differential Revision: https://reviews.llvm.org/D142685
Added:
llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
llvm/test/CodeGen/LoongArch/target-abi-from-triple.ll
Modified:
llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
index d8850f656d52f..a0136440ec0ee 100644
--- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
@@ -12,6 +12,7 @@
#include "LoongArchSubtarget.h"
#include "LoongArchFrameLowering.h"
+#include "MCTargetDesc/LoongArchBaseInfo.h"
using namespace llvm;
@@ -48,8 +49,8 @@ LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies(
if (!Is64Bit && HasLA64)
report_fatal_error("Feature 64bit should be used for loongarch64 target.");
- // TODO: ILP32{S,F} LP64{S,F}
- TargetABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D;
+ TargetABI = LoongArchABI::computeTargetABI(TT, ABIName);
+
return *this;
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
index de2ba2833414b..c7b1e19daa8be 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
@@ -15,11 +15,71 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace LoongArchABI {
+ABI computeTargetABI(const Triple &TT, StringRef ABIName) {
+ ABI ArgProvidedABI = getTargetABI(ABIName);
+ bool Is64Bit = TT.isArch64Bit();
+ ABI TripleABI;
+
+ // Figure out the ABI explicitly requested via the triple's environment type.
+ switch (TT.getEnvironment()) {
+ case llvm::Triple::EnvironmentType::GNUSF:
+ TripleABI = Is64Bit ? LoongArchABI::ABI_LP64S : LoongArchABI::ABI_ILP32S;
+ break;
+ case llvm::Triple::EnvironmentType::GNUF32:
+ TripleABI = Is64Bit ? LoongArchABI::ABI_LP64F : LoongArchABI::ABI_ILP32F;
+ break;
+
+ // Let the fallback case behave like {ILP32,LP64}D.
+ case llvm::Triple::EnvironmentType::GNUF64:
+ default:
+ TripleABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D;
+ break;
+ }
+
+ switch (ArgProvidedABI) {
+ case LoongArchABI::ABI_Unknown:
+ // Fallback to the triple-implied ABI if ABI name is not specified or
+ // invalid.
+ if (!ABIName.empty())
+ errs() << "'" << ABIName
+ << "' is not a recognized ABI for this target, ignoring and using "
+ "triple-implied ABI\n";
+ return TripleABI;
+
+ case LoongArchABI::ABI_ILP32S:
+ case LoongArchABI::ABI_ILP32F:
+ case LoongArchABI::ABI_ILP32D:
+ if (Is64Bit) {
+ errs() << "32-bit ABIs are not supported for 64-bit targets, ignoring "
+ "target-abi and using triple-implied ABI\n";
+ return TripleABI;
+ }
+ break;
+
+ case LoongArchABI::ABI_LP64S:
+ case LoongArchABI::ABI_LP64F:
+ case LoongArchABI::ABI_LP64D:
+ if (!Is64Bit) {
+ errs() << "64-bit ABIs are not supported for 32-bit targets, ignoring "
+ "target-abi and using triple-implied ABI\n";
+ return TripleABI;
+ }
+ break;
+ }
+
+ if (!ABIName.empty() && ArgProvidedABI != TripleABI)
+ errs() << "warning: triple-implied ABI conflicts with provided target-abi '"
+ << ABIName << "', using target-abi\n";
+
+ return ArgProvidedABI;
+}
+
ABI getTargetABI(StringRef ABIName) {
auto TargetABI = StringSwitch<ABI>(ABIName)
.Case("ilp32s", ABI_ILP32S)
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index c5f0726779999..cdbd1f5699dfd 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -54,6 +54,7 @@ enum ABI {
ABI_Unknown
};
+ABI computeTargetABI(const Triple &TT, StringRef ABIName);
ABI getTargetABI(StringRef ABIName);
// Returns the register used to hold the stack pointer after realignment.
diff --git a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
new file mode 100644
index 0000000000000..f30fcb8afeec2
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
@@ -0,0 +1,67 @@
+;; Check that an unknown --target-abi is ignored and the triple-implied ABI is
+;; used.
+; RUN: llc --mtriple=loongarch32-linux-gnu --target-abi=foo --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=ILP32D,UNKNOWN
+; RUN: llc --mtriple=loongarch64-linux-gnu --target-abi=foo --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=LP64D,UNKNOWN
+
+; UNKNOWN: 'foo' is not a recognized ABI for this target, ignoring and using triple-implied ABI
+
+;; Check that --target-abi takes precedence over triple-supplied ABI modifiers.
+; RUN: llc --mtriple=loongarch32-linux-gnusf --target-abi=ilp32d --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=ILP32D,CONFLICT-ILP32D
+; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64d --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=LP64D,CONFLICT-LP64D
+
+; CONFLICT-ILP32D: warning: triple-implied ABI conflicts with provided target-abi 'ilp32d', using target-abi
+; CONFLICT-LP64D: warning: triple-implied ABI conflicts with provided target-abi 'lp64d', using target-abi
+
+;; Check that ILP32-on-LA64 and LP64-on-LA32 combinations are handled properly.
+; RUN: llc --mtriple=loongarch64 --target-abi=ilp32d --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=LP64D,32ON64
+; RUN: llc --mtriple=loongarch32 --target-abi=lp64d --mattr=+d < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=ILP32D,64ON32
+
+; 32ON64: 32-bit ABIs are not supported for 64-bit targets, ignoring target-abi and using triple-implied ABI
+; 64ON32: 64-bit ABIs are not supported for 32-bit targets, ignoring target-abi and using triple-implied ABI
+
+define float @f(float %a) {
+; ILP32D-LABEL: f:
+; ILP32D: # %bb.0:
+; ILP32D-NEXT: addi.w $a0, $zero, 1
+; ILP32D-NEXT: movgr2fr.w $fa1, $a0
+; ILP32D-NEXT: ffint.s.w $fa1, $fa1
+; ILP32D-NEXT: fadd.s $fa0, $fa0, $fa1
+; ILP32D-NEXT: ret
+;
+; LP64D-LABEL: f:
+; LP64D: # %bb.0:
+; LP64D-NEXT: addi.w $a0, $zero, 1
+; LP64D-NEXT: movgr2fr.w $fa1, $a0
+; LP64D-NEXT: ffint.s.w $fa1, $fa1
+; LP64D-NEXT: fadd.s $fa0, $fa0, $fa1
+; LP64D-NEXT: ret
+ %1 = fadd float %a, 1.0
+ ret float %1
+}
+
+define double @g(double %a) {
+; ILP32D-LABEL: g:
+; ILP32D: # %bb.0:
+; ILP32D-NEXT: addi.w $a0, $zero, 1
+; ILP32D-NEXT: movgr2fr.w $fa1, $a0
+; ILP32D-NEXT: ffint.s.w $fa1, $fa1
+; ILP32D-NEXT: fcvt.d.s $fa1, $fa1
+; ILP32D-NEXT: fadd.d $fa0, $fa0, $fa1
+; ILP32D-NEXT: ret
+;
+; LP64D-LABEL: g:
+; LP64D: # %bb.0:
+; LP64D-NEXT: addi.d $a0, $zero, 1
+; LP64D-NEXT: movgr2fr.d $fa1, $a0
+; LP64D-NEXT: ffint.d.l $fa1, $fa1
+; LP64D-NEXT: fadd.d $fa0, $fa0, $fa1
+; LP64D-NEXT: ret
+ %1 = fadd double %a, 1.0
+ ret double %1
+}
diff --git a/llvm/test/CodeGen/LoongArch/target-abi-from-triple.ll b/llvm/test/CodeGen/LoongArch/target-abi-from-triple.ll
new file mode 100644
index 0000000000000..0aca339038860
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/target-abi-from-triple.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+
+;; Check that the correct ABI is chosen based on the triple given.
+;; TODO: enable the S and F ABIs once support is wired up.
+; RUN: llc --mtriple=loongarch32-linux-gnuf64 --mattr=+d < %s \
+; RUN: | FileCheck %s --check-prefix=ILP32D
+; RUN: llc --mtriple=loongarch64-linux-gnuf64 --mattr=+d < %s \
+; RUN: | FileCheck %s --check-prefix=LP64D
+
+define float @f(float %a) {
+; ILP32D-LABEL: f:
+; ILP32D: # %bb.0:
+; ILP32D-NEXT: addi.w $a0, $zero, 1
+; ILP32D-NEXT: movgr2fr.w $fa1, $a0
+; ILP32D-NEXT: ffint.s.w $fa1, $fa1
+; ILP32D-NEXT: fadd.s $fa0, $fa0, $fa1
+; ILP32D-NEXT: ret
+;
+; LP64D-LABEL: f:
+; LP64D: # %bb.0:
+; LP64D-NEXT: addi.w $a0, $zero, 1
+; LP64D-NEXT: movgr2fr.w $fa1, $a0
+; LP64D-NEXT: ffint.s.w $fa1, $fa1
+; LP64D-NEXT: fadd.s $fa0, $fa0, $fa1
+; LP64D-NEXT: ret
+ %1 = fadd float %a, 1.0
+ ret float %1
+}
+
+define double @g(double %a) {
+; ILP32D-LABEL: g:
+; ILP32D: # %bb.0:
+; ILP32D-NEXT: addi.w $a0, $zero, 1
+; ILP32D-NEXT: movgr2fr.w $fa1, $a0
+; ILP32D-NEXT: ffint.s.w $fa1, $fa1
+; ILP32D-NEXT: fcvt.d.s $fa1, $fa1
+; ILP32D-NEXT: fadd.d $fa0, $fa0, $fa1
+; ILP32D-NEXT: ret
+;
+; LP64D-LABEL: g:
+; LP64D: # %bb.0:
+; LP64D-NEXT: addi.d $a0, $zero, 1
+; LP64D-NEXT: movgr2fr.d $fa1, $a0
+; LP64D-NEXT: ffint.d.l $fa1, $fa1
+; LP64D-NEXT: fadd.d $fa0, $fa0, $fa1
+; LP64D-NEXT: ret
+ %1 = fadd double %a, 1.0
+ ret double %1
+}
More information about the llvm-commits
mailing list