[llvm] 70608c2 - [LoongArch] Refactor LoongArchABI::computeTargetABI

via llvm-commits llvm-commits at lists.llvm.org
Thu May 16 02:15:25 PDT 2024


Author: wanglei
Date: 2024-05-16T17:15:21+08:00
New Revision: 70608c24fae8943cb93276db4d0358722705507b

URL: https://github.com/llvm/llvm-project/commit/70608c24fae8943cb93276db4d0358722705507b
DIFF: https://github.com/llvm/llvm-project/commit/70608c24fae8943cb93276db4d0358722705507b.diff

LOG: [LoongArch] Refactor LoongArchABI::computeTargetABI

The previous logic did not consider whether the architectural features
meet the requirements of the ABI, resulting in the generation of
incorrect object files in some cases. For example:

```
llc -mtriple=loongarch64 -filetype=obj test/CodeGen/LoongArch/ir-instruction/fadd.ll -o t.o
llvm-readelf -h t.o
```
The object file indicates the ABI as lp64d, however, the generated code
is lp64s.

The new logic introduces the `feature-implied` ABI. When both target-abi
and triple-implied ABI are invalid, the feature-implied ABI is used.

Reviewed By: SixWeining, xen0n

Pull Request: https://github.com/llvm/llvm-project/pull/92223

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
    llvm/test/CodeGen/LoongArch/e_flags.ll
    llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
index ffcde7dd1fa74..57babfc917f89 100644
--- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
@@ -50,7 +50,7 @@ LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies(
   if (!Is64Bit && HasLA64)
     report_fatal_error("Feature 64bit should be used for loongarch64 target.");
 
-  TargetABI = LoongArchABI::computeTargetABI(TT, ABIName);
+  TargetABI = LoongArchABI::computeTargetABI(TT, getFeatureBits(), ABIName);
 
   return *this;
 }

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
index 6d75e575cd3cf..17bcacedfc511 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "LoongArchBaseInfo.h"
+#include "LoongArchMCTargetDesc.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -49,63 +50,127 @@ static ABI checkABIStandardized(ABI Abi) {
   return Abi;
 }
 
-ABI computeTargetABI(const Triple &TT, StringRef ABIName) {
-  ABI ArgProvidedABI = getTargetABI(ABIName);
+static ABI getTripleABI(const Triple &TT) {
   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;
+    TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
     break;
   case llvm::Triple::EnvironmentType::GNUF32:
-    TripleABI = Is64Bit ? LoongArchABI::ABI_LP64F : LoongArchABI::ABI_ILP32F;
+    TripleABI = Is64Bit ? ABI_LP64F : 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;
+    TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D;
     break;
   }
+  return TripleABI;
+}
 
-  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 checkABIStandardized(TripleABI);
+ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
+                     StringRef ABIName) {
+  bool Is64Bit = TT.isArch64Bit();
+  ABI ArgProvidedABI = getTargetABI(ABIName);
+  ABI TripleABI = getTripleABI(TT);
+
+  auto IsABIValidForFeature = [=](ABI Abi) {
+    switch (Abi) {
+    default:
+      return false;
+    case ABI_ILP32S:
+      return !Is64Bit;
+    case ABI_ILP32F:
+      return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
+    case ABI_ILP32D:
+      return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
+    case ABI_LP64S:
+      return Is64Bit;
+    case ABI_LP64F:
+      return Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
+    case ABI_LP64D:
+      return Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
+    }
+  };
+
+  // 1. If the '-target-abi' is valid, use it.
+  if (IsABIValidForFeature(ArgProvidedABI)) {
+    if (TT.hasEnvironment() && ArgProvidedABI != TripleABI)
+      errs()
+          << "warning: triple-implied ABI conflicts with provided target-abi '"
+          << ABIName << "', using target-abi\n";
+    return checkABIStandardized(ArgProvidedABI);
+  }
 
-  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";
+  // 2. If the triple-implied ABI is valid, use it.
+  if (IsABIValidForFeature(TripleABI)) {
+    // If target-abi is not specified, use the valid triple-implied ABI.
+    if (ABIName.empty())
       return checkABIStandardized(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";
+    switch (ArgProvidedABI) {
+    case ABI_Unknown:
+      // Fallback to the triple-implied ABI if ABI name is specified but
+      // invalid.
+      errs() << "warning: the '" << ABIName
+             << "' is not a recognized ABI for this target, ignoring and "
+                "using triple-implied ABI\n";
       return checkABIStandardized(TripleABI);
+    case ABI_ILP32S:
+    case ABI_ILP32F:
+    case ABI_ILP32D:
+      if (Is64Bit) {
+        errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, "
+                  "ignoring and using triple-implied ABI\n";
+        return checkABIStandardized(TripleABI);
+      }
+      break;
+    case ABI_LP64S:
+    case ABI_LP64F:
+    case ABI_LP64D:
+      if (!Is64Bit) {
+        errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, "
+                  "ignoring and using triple-implied ABI\n";
+        return checkABIStandardized(TripleABI);
+      }
+      break;
     }
-    break;
-  }
 
-  if (!ABIName.empty() && TT.hasEnvironment() && ArgProvidedABI != TripleABI)
-    errs() << "warning: triple-implied ABI conflicts with provided target-abi '"
-           << ABIName << "', using target-abi\n";
+    switch (ArgProvidedABI) {
+    case ABI_ILP32F:
+    case ABI_LP64F:
+      errs() << "warning: the '" << ABIName
+             << "' ABI can't be used for a target that doesn't support the 'F' "
+                "instruction set, ignoring and using triple-implied ABI\n";
+      break;
+    case ABI_ILP32D:
+    case ABI_LP64D:
+      errs() << "warning: the '" << ABIName
+             << "' ABI can't be used for a target that doesn't support the 'D' "
+                "instruction set, ignoring and using triple-implied ABI\n";
+      break;
+    default:
+      llvm_unreachable("");
+    }
+    return checkABIStandardized(TripleABI);
+  }
 
-  return checkABIStandardized(ArgProvidedABI);
+  // 3. Parse the 'feature-abi', and use it.
+  auto GetFeatureABI = [=]() {
+    if (FeatureBits[LoongArch::FeatureBasicD])
+      return Is64Bit ? ABI_LP64D : ABI_ILP32D;
+    if (FeatureBits[LoongArch::FeatureBasicF])
+      return Is64Bit ? ABI_LP64F : ABI_ILP32F;
+    return Is64Bit ? ABI_LP64S : ABI_ILP32S;
+  };
+  if (ABIName.empty())
+    errs() << "warning: the triple-implied ABI is invalid, ignoring and using "
+              "feature-implied ABI\n";
+  else
+    errs() << "warning: both target-abi and the triple-implied ABI are "
+              "invalid, ignoring and using feature-implied ABI\n";
+  return checkABIStandardized(GetFeatureABI());
 }
 
 ABI getTargetABI(StringRef ABIName) {

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 3c3fed7d43ed9..1a12fb492a60f 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -69,7 +69,8 @@ enum ABI {
   ABI_Unknown
 };
 
-ABI computeTargetABI(const Triple &TT, StringRef ABIName);
+ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
+                     StringRef ABIName);
 ABI getTargetABI(StringRef ABIName);
 
 // Returns the register used to hold the stack pointer after realignment.

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
index 9e56333e5fd9b..a8a4f1ed327d3 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
@@ -27,7 +27,8 @@ LoongArchTargetELFStreamer::LoongArchTargetELFStreamer(
   auto &MAB = static_cast<LoongArchAsmBackend &>(
       getStreamer().getAssembler().getBackend());
   setTargetABI(LoongArchABI::computeTargetABI(
-      STI.getTargetTriple(), MAB.getTargetOptions().getABIName()));
+      STI.getTargetTriple(), STI.getFeatureBits(),
+      MAB.getTargetOptions().getABIName()));
 }
 
 MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() {

diff  --git a/llvm/test/CodeGen/LoongArch/e_flags.ll b/llvm/test/CodeGen/LoongArch/e_flags.ll
index 25f3285bdf328..2feb9d832bca9 100644
--- a/llvm/test/CodeGen/LoongArch/e_flags.ll
+++ b/llvm/test/CodeGen/LoongArch/e_flags.ll
@@ -4,10 +4,10 @@
 ; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32s -o %t-ilp32s
 ; RUN: llvm-readelf -h %t-ilp32s | FileCheck %s --check-prefixes=ILP32,ABI-S --match-full-lines
 
-; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f
+; RUN: llc --mtriple=loongarch32 -mattr=+f --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f
 ; RUN: llvm-readelf -h %t-ilp32f | FileCheck %s --check-prefixes=ILP32,ABI-F --match-full-lines
 
-; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d
+; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d
 ; RUN: llvm-readelf -h %t-ilp32d | FileCheck %s --check-prefixes=ILP32,ABI-D --match-full-lines
 
 ; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj %s -o %t-la64
@@ -16,7 +16,7 @@
 ; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64s -o %t-lp64s
 ; RUN: llvm-readelf -h %t-lp64s | FileCheck %s --check-prefixes=LP64,ABI-S --match-full-lines
 
-; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64f -o %t-lp64f
+; RUN: llc --mtriple=loongarch64 -mattr=+f --filetype=obj %s --target-abi=lp64f -o %t-lp64f
 ; RUN: llvm-readelf -h %t-lp64f | FileCheck %s --check-prefixes=LP64,ABI-F --match-full-lines
 
 ; RUN: llc --mtriple=loongarch64 --filetype=obj %s --mattr=+d --target-abi=lp64d -o %t-lp64d

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
index 1d5ed089c69fa..36b78ea2ea02c 100644
--- a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
+++ b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
@@ -5,7 +5,7 @@
 ; 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
+; UNKNOWN: warning: the '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 \
@@ -29,8 +29,31 @@
 ; 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
+; 32ON64: warning: 32-bit ABIs are not supported for 64-bit targets, ignoring and using triple-implied ABI
+; 64ON32: warning: 64-bit ABIs are not supported for 32-bit targets, ignoring and using triple-implied ABI
+
+;; Check that target-abi is invalid but triple-implied ABI is valid, use triple-implied ABI
+; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64f --mattr=-f < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefixes=LP64S,LP64S-LP64F-NOF
+; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64d --mattr=-d < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefixes=LP64S,LP64S-LP64D-NOD
+
+; LP64S-LP64F-NOF: warning: the 'lp64f' ABI can't be used for a target that doesn't support the 'F' instruction set, ignoring and using triple-implied ABI
+; LP64S-LP64D-NOD: warning: the 'lp64d' ABI can't be used for a target that doesn't support the 'D' instruction set, ignoring and using triple-implied ABI
+
+;; Check that both target-abi and triple-implied ABI are invalid, use feature-implied ABI
+; RUN: llc --mtriple=loongarch64-linux-gnuf64 --target-abi=lp64f --mattr=-f < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF
+; RUN: llc --mtriple=loongarch64 --target-abi=lp64f --mattr=-f < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF
+
+; LP64D-LP64F-NOF: warning: both target-abi and the triple-implied ABI are invalid, ignoring and using feature-implied ABI
+
+;; Check that triple-implied ABI are invalid, use feature-implied ABI
+; RUN: llc --mtriple=loongarch64 --mattr=-f < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefixes=LP64S,LP64D-NONE-NOF
+
+; LP64D-NONE-NOF: warning: the triple-implied ABI is invalid, ignoring and using feature-implied ABI
 
 define float @f(float %a) {
 ; ILP32D-LABEL: f:
@@ -48,6 +71,9 @@ define float @f(float %a) {
 ; LP64D-NEXT:    ffint.s.w $fa1, $fa1
 ; LP64D-NEXT:    fadd.s $fa0, $fa0, $fa1
 ; LP64D-NEXT:    ret
+;
+; LP64S-LABEL: f:
+; LP64S:         bl %plt(__addsf3)
   %1 = fadd float %a, 1.0
   ret float %1
 }
@@ -69,6 +95,9 @@ define double @g(double %a) {
 ; LP64D-NEXT:    ffint.d.l $fa1, $fa1
 ; LP64D-NEXT:    fadd.d $fa0, $fa0, $fa1
 ; LP64D-NEXT:    ret
+;
+; LP64S-LABEL: g:
+; LP64S:         bl %plt(__adddf3)
   %1 = fadd double %a, 1.0
   ret double %1
 }


        


More information about the llvm-commits mailing list