llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-loongarch Author: wanglei (wangleiat) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/92223.diff 6 Files Affected: - (modified) llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp (+1-1) - (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp (+102-35) - (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h (+2-1) - (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp (+2-1) - (modified) llvm/test/CodeGen/LoongArch/e_flags.ll (+3-3) - (modified) llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll (+23) ``````````diff 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 7fd2526a57c94..a8f3b8b079c08 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" @@ -52,63 +53,129 @@ 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; +} + +ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, + StringRef ABIName) { + bool Is64Bit = TT.isArch64Bit(); + ABI ArgProvidedABI = getTargetABI(ABIName); + ABI TripleABI = getTripleABI(TT); + + 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; + }; + auto IsValidABI = [=](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 (IsValidABI(ArgProvidedABI)) { + if (TT.hasEnvironment() && ArgProvidedABI != TripleABI) + errs() + << "warning: triple-implied ABI conflicts with provided target-abi '" + << ABIName << "', using target-abi\n"; + return checkABIStandardized(ArgProvidedABI); + } + + // 2. If the triple-implied ABI is valid, use it. + if (IsValidABI(TripleABI)) { + // If not specifie target-abi, use the valid triple-implied ABI. + if (ABIName.empty()) + return checkABIStandardized(TripleABI); - switch (ArgProvidedABI) { - case LoongArchABI::ABI_Unknown: - // Fallback to the triple-implied ABI if ABI name is not specified or - // invalid. - if (!ABIName.empty()) + switch (ArgProvidedABI) { + case ABI_Unknown: + // Fallback to the triple-implied ABI if ABI name is specified and + // invalid. errs() << "'" << ABIName << "' is not a recognized ABI for this target, ignoring and using " "triple-implied ABI\n"; - return checkABIStandardized(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 checkABIStandardized(TripleABI); + case ABI_ILP32S: + case ABI_ILP32F: + case 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 checkABIStandardized(TripleABI); + } + break; + case ABI_LP64S: + case ABI_LP64F: + case 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 checkABIStandardized(TripleABI); + } + break; } - 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 checkABIStandardized(TripleABI); + switch (ArgProvidedABI) { + case ABI_ILP32F: + case ABI_LP64F: + errs() << "'" << ABIName + << "' ABI can't be used for a target that doesn't support the 'F' " + "instruction set, ignoring target-abi and using triple-implied " + "ABI\n"; + break; + case ABI_ILP32D: + case ABI_LP64D: + errs() << "'" << ABIName + << "' ABI can't be used for a target that doesn't support the 'D' " + "instruction set, ignoring target-abi and using triple-implied " + "ABI\n"; + break; + default: + llvm_unreachable(""); } - break; + return checkABIStandardized(TripleABI); } - if (!ABIName.empty() && TT.hasEnvironment() && ArgProvidedABI != TripleABI) - errs() << "warning: triple-implied ABI conflicts with provided target-abi '" - << ABIName << "', using target-abi\n"; - - return checkABIStandardized(ArgProvidedABI); + // 3. Parse the 'feature-abi', and use it. + if (ABIName.empty()) + errs() << "The triple-implied ABI is invalid, ignoring triple-implied ABI " + "and using feature-implied ABI\n"; + else + errs() << "The target-abi and triple-implied ABI are invalid, ignoring " + "them 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..457d33ca93659 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 @@ -32,6 +32,23 @@ ; 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 +;; 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: 'lp64f' ABI can't be used for a target that doesn't support the 'F' instruction set, ignoring target-abi and using triple-implied ABI +; LP64S-LP64D-NOD: 'lp64d' ABI can't be used for a target that doesn't support the 'D' instruction set, ignoring target-abi 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: The target-abi and triple-implied ABI are invalid, ignoring them and using feature-implied ABI + define float @f(float %a) { ; ILP32D-LABEL: f: ; ILP32D: # %bb.0: @@ -48,6 +65,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 +89,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 } `````````` </details> https://github.com/llvm/llvm-project/pull/92223 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits