Skip to content

[LoongArch] Refactor LoongArchABI::computeTargetABI #92223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
139 changes: 102 additions & 37 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/LoongArch/e_flags.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
35 changes: 32 additions & 3 deletions llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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:
Expand All @@ -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
}
Expand All @@ -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
}
Loading