[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