Skip to content

Commit 70608c2

Browse files
authored
[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: #92223
1 parent 3041001 commit 70608c2

File tree

6 files changed

+142
-46
lines changed

6 files changed

+142
-46
lines changed

llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies(
5050
if (!Is64Bit && HasLA64)
5151
report_fatal_error("Feature 64bit should be used for loongarch64 target.");
5252

53-
TargetABI = LoongArchABI::computeTargetABI(TT, ABIName);
53+
TargetABI = LoongArchABI::computeTargetABI(TT, getFeatureBits(), ABIName);
5454

5555
return *this;
5656
}

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "LoongArchBaseInfo.h"
15+
#include "LoongArchMCTargetDesc.h"
1516
#include "llvm/ADT/ArrayRef.h"
1617
#include "llvm/MC/MCSubtargetInfo.h"
1718
#include "llvm/Support/ErrorHandling.h"
@@ -49,63 +50,127 @@ static ABI checkABIStandardized(ABI Abi) {
4950
return Abi;
5051
}
5152

52-
ABI computeTargetABI(const Triple &TT, StringRef ABIName) {
53-
ABI ArgProvidedABI = getTargetABI(ABIName);
53+
static ABI getTripleABI(const Triple &TT) {
5454
bool Is64Bit = TT.isArch64Bit();
5555
ABI TripleABI;
56-
57-
// Figure out the ABI explicitly requested via the triple's environment type.
5856
switch (TT.getEnvironment()) {
5957
case llvm::Triple::EnvironmentType::GNUSF:
60-
TripleABI = Is64Bit ? LoongArchABI::ABI_LP64S : LoongArchABI::ABI_ILP32S;
58+
TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
6159
break;
6260
case llvm::Triple::EnvironmentType::GNUF32:
63-
TripleABI = Is64Bit ? LoongArchABI::ABI_LP64F : LoongArchABI::ABI_ILP32F;
61+
TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;
6462
break;
65-
6663
// Let the fallback case behave like {ILP32,LP64}D.
6764
case llvm::Triple::EnvironmentType::GNUF64:
6865
default:
69-
TripleABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D;
66+
TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D;
7067
break;
7168
}
69+
return TripleABI;
70+
}
7271

73-
switch (ArgProvidedABI) {
74-
case LoongArchABI::ABI_Unknown:
75-
// Fallback to the triple-implied ABI if ABI name is not specified or
76-
// invalid.
77-
if (!ABIName.empty())
78-
errs() << "'" << ABIName
79-
<< "' is not a recognized ABI for this target, ignoring and using "
80-
"triple-implied ABI\n";
81-
return checkABIStandardized(TripleABI);
72+
ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
73+
StringRef ABIName) {
74+
bool Is64Bit = TT.isArch64Bit();
75+
ABI ArgProvidedABI = getTargetABI(ABIName);
76+
ABI TripleABI = getTripleABI(TT);
77+
78+
auto IsABIValidForFeature = [=](ABI Abi) {
79+
switch (Abi) {
80+
default:
81+
return false;
82+
case ABI_ILP32S:
83+
return !Is64Bit;
84+
case ABI_ILP32F:
85+
return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
86+
case ABI_ILP32D:
87+
return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
88+
case ABI_LP64S:
89+
return Is64Bit;
90+
case ABI_LP64F:
91+
return Is64Bit && FeatureBits[LoongArch::FeatureBasicF];
92+
case ABI_LP64D:
93+
return Is64Bit && FeatureBits[LoongArch::FeatureBasicD];
94+
}
95+
};
96+
97+
// 1. If the '-target-abi' is valid, use it.
98+
if (IsABIValidForFeature(ArgProvidedABI)) {
99+
if (TT.hasEnvironment() && ArgProvidedABI != TripleABI)
100+
errs()
101+
<< "warning: triple-implied ABI conflicts with provided target-abi '"
102+
<< ABIName << "', using target-abi\n";
103+
return checkABIStandardized(ArgProvidedABI);
104+
}
82105

83-
case LoongArchABI::ABI_ILP32S:
84-
case LoongArchABI::ABI_ILP32F:
85-
case LoongArchABI::ABI_ILP32D:
86-
if (Is64Bit) {
87-
errs() << "32-bit ABIs are not supported for 64-bit targets, ignoring "
88-
"target-abi and using triple-implied ABI\n";
106+
// 2. If the triple-implied ABI is valid, use it.
107+
if (IsABIValidForFeature(TripleABI)) {
108+
// If target-abi is not specified, use the valid triple-implied ABI.
109+
if (ABIName.empty())
89110
return checkABIStandardized(TripleABI);
90-
}
91-
break;
92111

93-
case LoongArchABI::ABI_LP64S:
94-
case LoongArchABI::ABI_LP64F:
95-
case LoongArchABI::ABI_LP64D:
96-
if (!Is64Bit) {
97-
errs() << "64-bit ABIs are not supported for 32-bit targets, ignoring "
98-
"target-abi and using triple-implied ABI\n";
112+
switch (ArgProvidedABI) {
113+
case ABI_Unknown:
114+
// Fallback to the triple-implied ABI if ABI name is specified but
115+
// invalid.
116+
errs() << "warning: the '" << ABIName
117+
<< "' is not a recognized ABI for this target, ignoring and "
118+
"using triple-implied ABI\n";
99119
return checkABIStandardized(TripleABI);
120+
case ABI_ILP32S:
121+
case ABI_ILP32F:
122+
case ABI_ILP32D:
123+
if (Is64Bit) {
124+
errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, "
125+
"ignoring and using triple-implied ABI\n";
126+
return checkABIStandardized(TripleABI);
127+
}
128+
break;
129+
case ABI_LP64S:
130+
case ABI_LP64F:
131+
case ABI_LP64D:
132+
if (!Is64Bit) {
133+
errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, "
134+
"ignoring and using triple-implied ABI\n";
135+
return checkABIStandardized(TripleABI);
136+
}
137+
break;
100138
}
101-
break;
102-
}
103139

104-
if (!ABIName.empty() && TT.hasEnvironment() && ArgProvidedABI != TripleABI)
105-
errs() << "warning: triple-implied ABI conflicts with provided target-abi '"
106-
<< ABIName << "', using target-abi\n";
140+
switch (ArgProvidedABI) {
141+
case ABI_ILP32F:
142+
case ABI_LP64F:
143+
errs() << "warning: the '" << ABIName
144+
<< "' ABI can't be used for a target that doesn't support the 'F' "
145+
"instruction set, ignoring and using triple-implied ABI\n";
146+
break;
147+
case ABI_ILP32D:
148+
case ABI_LP64D:
149+
errs() << "warning: the '" << ABIName
150+
<< "' ABI can't be used for a target that doesn't support the 'D' "
151+
"instruction set, ignoring and using triple-implied ABI\n";
152+
break;
153+
default:
154+
llvm_unreachable("");
155+
}
156+
return checkABIStandardized(TripleABI);
157+
}
107158

108-
return checkABIStandardized(ArgProvidedABI);
159+
// 3. Parse the 'feature-abi', and use it.
160+
auto GetFeatureABI = [=]() {
161+
if (FeatureBits[LoongArch::FeatureBasicD])
162+
return Is64Bit ? ABI_LP64D : ABI_ILP32D;
163+
if (FeatureBits[LoongArch::FeatureBasicF])
164+
return Is64Bit ? ABI_LP64F : ABI_ILP32F;
165+
return Is64Bit ? ABI_LP64S : ABI_ILP32S;
166+
};
167+
if (ABIName.empty())
168+
errs() << "warning: the triple-implied ABI is invalid, ignoring and using "
169+
"feature-implied ABI\n";
170+
else
171+
errs() << "warning: both target-abi and the triple-implied ABI are "
172+
"invalid, ignoring and using feature-implied ABI\n";
173+
return checkABIStandardized(GetFeatureABI());
109174
}
110175

111176
ABI getTargetABI(StringRef ABIName) {

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ enum ABI {
6969
ABI_Unknown
7070
};
7171

72-
ABI computeTargetABI(const Triple &TT, StringRef ABIName);
72+
ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
73+
StringRef ABIName);
7374
ABI getTargetABI(StringRef ABIName);
7475

7576
// Returns the register used to hold the stack pointer after realignment.

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ LoongArchTargetELFStreamer::LoongArchTargetELFStreamer(
2727
auto &MAB = static_cast<LoongArchAsmBackend &>(
2828
getStreamer().getAssembler().getBackend());
2929
setTargetABI(LoongArchABI::computeTargetABI(
30-
STI.getTargetTriple(), MAB.getTargetOptions().getABIName()));
30+
STI.getTargetTriple(), STI.getFeatureBits(),
31+
MAB.getTargetOptions().getABIName()));
3132
}
3233

3334
MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() {

llvm/test/CodeGen/LoongArch/e_flags.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32s -o %t-ilp32s
55
; RUN: llvm-readelf -h %t-ilp32s | FileCheck %s --check-prefixes=ILP32,ABI-S --match-full-lines
66

7-
; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f
7+
; RUN: llc --mtriple=loongarch32 -mattr=+f --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f
88
; RUN: llvm-readelf -h %t-ilp32f | FileCheck %s --check-prefixes=ILP32,ABI-F --match-full-lines
99

10-
; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d
10+
; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d
1111
; RUN: llvm-readelf -h %t-ilp32d | FileCheck %s --check-prefixes=ILP32,ABI-D --match-full-lines
1212

1313
; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj %s -o %t-la64
@@ -16,7 +16,7 @@
1616
; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64s -o %t-lp64s
1717
; RUN: llvm-readelf -h %t-lp64s | FileCheck %s --check-prefixes=LP64,ABI-S --match-full-lines
1818

19-
; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64f -o %t-lp64f
19+
; RUN: llc --mtriple=loongarch64 -mattr=+f --filetype=obj %s --target-abi=lp64f -o %t-lp64f
2020
; RUN: llvm-readelf -h %t-lp64f | FileCheck %s --check-prefixes=LP64,ABI-F --match-full-lines
2121

2222
; RUN: llc --mtriple=loongarch64 --filetype=obj %s --mattr=+d --target-abi=lp64d -o %t-lp64d

llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
; RUN: llc --mtriple=loongarch64-linux-gnu --target-abi=foo --mattr=+d < %s 2>&1 \
66
; RUN: | FileCheck %s --check-prefixes=LP64D,UNKNOWN
77

8-
; UNKNOWN: 'foo' is not a recognized ABI for this target, ignoring and using triple-implied ABI
8+
; UNKNOWN: warning: the 'foo' is not a recognized ABI for this target, ignoring and using triple-implied ABI
99

1010
;; Check that --target-abi takes precedence over triple-supplied ABI modifiers.
1111
; RUN: llc --mtriple=loongarch32-linux-gnusf --target-abi=ilp32d --mattr=+d < %s 2>&1 \
@@ -29,8 +29,31 @@
2929
; RUN: llc --mtriple=loongarch32 --target-abi=lp64d --mattr=+d < %s 2>&1 \
3030
; RUN: | FileCheck %s --check-prefixes=ILP32D,64ON32
3131

32-
; 32ON64: 32-bit ABIs are not supported for 64-bit targets, ignoring target-abi and using triple-implied ABI
33-
; 64ON32: 64-bit ABIs are not supported for 32-bit targets, ignoring target-abi and using triple-implied ABI
32+
; 32ON64: warning: 32-bit ABIs are not supported for 64-bit targets, ignoring and using triple-implied ABI
33+
; 64ON32: warning: 64-bit ABIs are not supported for 32-bit targets, ignoring and using triple-implied ABI
34+
35+
;; Check that target-abi is invalid but triple-implied ABI is valid, use triple-implied ABI
36+
; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64f --mattr=-f < %s 2>&1 \
37+
; RUN: | FileCheck %s --check-prefixes=LP64S,LP64S-LP64F-NOF
38+
; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64d --mattr=-d < %s 2>&1 \
39+
; RUN: | FileCheck %s --check-prefixes=LP64S,LP64S-LP64D-NOD
40+
41+
; 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
42+
; 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
43+
44+
;; Check that both target-abi and triple-implied ABI are invalid, use feature-implied ABI
45+
; RUN: llc --mtriple=loongarch64-linux-gnuf64 --target-abi=lp64f --mattr=-f < %s 2>&1 \
46+
; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF
47+
; RUN: llc --mtriple=loongarch64 --target-abi=lp64f --mattr=-f < %s 2>&1 \
48+
; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF
49+
50+
; LP64D-LP64F-NOF: warning: both target-abi and the triple-implied ABI are invalid, ignoring and using feature-implied ABI
51+
52+
;; Check that triple-implied ABI are invalid, use feature-implied ABI
53+
; RUN: llc --mtriple=loongarch64 --mattr=-f < %s 2>&1 \
54+
; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-NONE-NOF
55+
56+
; LP64D-NONE-NOF: warning: the triple-implied ABI is invalid, ignoring and using feature-implied ABI
3457

3558
define float @f(float %a) {
3659
; ILP32D-LABEL: f:
@@ -48,6 +71,9 @@ define float @f(float %a) {
4871
; LP64D-NEXT: ffint.s.w $fa1, $fa1
4972
; LP64D-NEXT: fadd.s $fa0, $fa0, $fa1
5073
; LP64D-NEXT: ret
74+
;
75+
; LP64S-LABEL: f:
76+
; LP64S: bl %plt(__addsf3)
5177
%1 = fadd float %a, 1.0
5278
ret float %1
5379
}
@@ -69,6 +95,9 @@ define double @g(double %a) {
6995
; LP64D-NEXT: ffint.d.l $fa1, $fa1
7096
; LP64D-NEXT: fadd.d $fa0, $fa0, $fa1
7197
; LP64D-NEXT: ret
98+
;
99+
; LP64S-LABEL: g:
100+
; LP64S: bl %plt(__adddf3)
72101
%1 = fadd double %a, 1.0
73102
ret double %1
74103
}

0 commit comments

Comments
 (0)