Skip to content

Commit 564b81d

Browse files
authored
Add support for x87 registers on GISel register selection (llvm#83528)
We handle 3 register classes for x87 - rfp32, rfp64 and rfp80. 1. X87 registers are assigned a pseudo register class. We need a new register bank for these classes. 2. We add bank information and enums for these. 3. Legalizer is updated to allow 32b and 64b even in absence of SSE. This is required because with SSE enabled, x86 doesn't use fp stack and instead uses SSE registers. 4. Functions in X86RegisterBankInfo need to decide whether to use the pseudo classes or SSE-enabled classes. I add MachineInstr as an argument to static helper function getPartialMappingIdx to this end. Add/Update tests.
1 parent 1a67dee commit 564b81d

File tree

7 files changed

+298
-25
lines changed

7 files changed

+298
-25
lines changed

llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
3939
bool HasVLX = Subtarget.hasVLX();
4040
bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();
4141
bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();
42+
bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();
4243

4344
const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
4445
const LLT s1 = LLT::scalar(1);
@@ -415,17 +416,19 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
415416
// fp constants
416417
getActionDefinitionsBuilder(G_FCONSTANT)
417418
.legalIf([=](const LegalityQuery &Query) -> bool {
418-
return (HasSSE1 && typeInSet(0, {s32})(Query)) ||
419-
(HasSSE2 && typeInSet(0, {s64})(Query));
419+
return (typeInSet(0, {s32, s64})(Query)) ||
420+
(UseX87 && typeInSet(0, {s80})(Query));
420421
});
421422

422423
// fp arithmetic
423424
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
424425
.legalIf([=](const LegalityQuery &Query) {
425-
return (HasSSE1 && typeInSet(0, {s32, v4s32})(Query)) ||
426-
(HasSSE2 && typeInSet(0, {s64, v2s64})(Query)) ||
426+
return (typeInSet(0, {s32, s64})(Query)) ||
427+
(HasSSE1 && typeInSet(0, {v4s32})(Query)) ||
428+
(HasSSE2 && typeInSet(0, {v2s64})(Query)) ||
427429
(HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) ||
428-
(HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query));
430+
(HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) ||
431+
(UseX87 && typeInSet(0, {s80})(Query));
429432
});
430433

431434
// fp comparison

llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "X86RegisterBankInfo.h"
1414
#include "X86InstrInfo.h"
15+
#include "X86Subtarget.h"
1516
#include "llvm/CodeGen/MachineRegisterInfo.h"
1617
#include "llvm/CodeGen/RegisterBank.h"
1718
#include "llvm/CodeGen/RegisterBankInfo.h"
@@ -59,11 +60,24 @@ X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
5960
X86::VR512RegClass.hasSubClassEq(&RC))
6061
return getRegBank(X86::VECRRegBankID);
6162

63+
if (X86::RFP80RegClass.hasSubClassEq(&RC) ||
64+
X86::RFP32RegClass.hasSubClassEq(&RC) ||
65+
X86::RFP64RegClass.hasSubClassEq(&RC))
66+
return getRegBank(X86::PSRRegBankID);
67+
6268
llvm_unreachable("Unsupported register kind yet.");
6369
}
6470

6571
X86GenRegisterBankInfo::PartialMappingIdx
66-
X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
72+
X86GenRegisterBankInfo::getPartialMappingIdx(const MachineInstr &MI,
73+
const LLT &Ty, bool isFP) {
74+
const MachineFunction *MF = MI.getMF();
75+
const X86Subtarget *ST = &MF->getSubtarget<X86Subtarget>();
76+
bool HasSSE1 = ST->hasSSE1();
77+
bool HasSSE2 = ST->hasSSE2();
78+
// 80 bits is only generated for X87 floating points.
79+
if (Ty.getSizeInBits() == 80)
80+
isFP = true;
6781
if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
6882
switch (Ty.getSizeInBits()) {
6983
case 1:
@@ -84,11 +98,13 @@ X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
8498
} else if (Ty.isScalar()) {
8599
switch (Ty.getSizeInBits()) {
86100
case 32:
87-
return PMI_FP32;
101+
return HasSSE1 ? PMI_FP32 : PMI_PSR32;
88102
case 64:
89-
return PMI_FP64;
103+
return HasSSE2 ? PMI_FP64 : PMI_PSR64;
90104
case 128:
91105
return PMI_VEC128;
106+
case 80:
107+
return PMI_PSR80;
92108
default:
93109
llvm_unreachable("Unsupported register size.");
94110
}
@@ -118,7 +134,8 @@ void X86RegisterBankInfo::getInstrPartialMappingIdxs(
118134
if (!MO.isReg() || !MO.getReg())
119135
OpRegBankIdx[Idx] = PMI_None;
120136
else
121-
OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
137+
OpRegBankIdx[Idx] =
138+
getPartialMappingIdx(MI, MRI.getType(MO.getReg()), isFP);
122139
}
123140
}
124141

@@ -156,7 +173,7 @@ X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
156173
(Ty != MRI.getType(MI.getOperand(2).getReg())))
157174
llvm_unreachable("Unsupported operand mapping yet.");
158175

159-
auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
176+
auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, isFP), 3);
160177
return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
161178
}
162179

@@ -190,9 +207,8 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
190207
unsigned NumOperands = MI.getNumOperands();
191208
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
192209

193-
auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
210+
auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, false), 3);
194211
return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
195-
196212
}
197213
default:
198214
break;
@@ -206,7 +222,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
206222
case TargetOpcode::G_FPTRUNC:
207223
case TargetOpcode::G_FCONSTANT:
208224
// Instruction having only floating-point operands (all scalars in VECRReg)
209-
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
225+
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
210226
break;
211227
case TargetOpcode::G_SITOFP:
212228
case TargetOpcode::G_FPTOSI: {
@@ -219,8 +235,8 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
219235

220236
bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
221237
bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
222-
OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
223-
OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
238+
OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);
239+
OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ SecondArgIsFP);
224240
break;
225241
}
226242
case TargetOpcode::G_FCMP: {
@@ -234,7 +250,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
234250
(void)Size;
235251
assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
236252

237-
auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
253+
auto FpRegBank = getPartialMappingIdx(MI, Ty1, /* isFP= */ true);
238254
OpRegBankIdx = {PMI_GPR8,
239255
/* Predicate */ PMI_None, FpRegBank, FpRegBank};
240256
break;
@@ -253,12 +269,12 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
253269
(Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
254270
Opc == TargetOpcode::G_ANYEXT;
255271

256-
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
272+
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ isFPTrunc || isFPAnyExt,
257273
OpRegBankIdx);
258274
} break;
259275
default:
260276
// Track the bank of each register, use NotFP mapping (all scalars in GPRs)
261-
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
277+
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ false, OpRegBankIdx);
262278
break;
263279
}
264280

@@ -288,16 +304,16 @@ X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
288304
case TargetOpcode::G_LOAD:
289305
case TargetOpcode::G_STORE:
290306
case TargetOpcode::G_IMPLICIT_DEF: {
291-
// we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
307+
// we going to try to map 32/64/80 bit to PMI_FP32/PMI_FP64/PMI_FP80
292308
unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
293-
if (Size != 32 && Size != 64)
309+
if (Size != 32 && Size != 64 && Size != 80)
294310
break;
295311

296312
unsigned NumOperands = MI.getNumOperands();
297313

298314
// Track the bank of each register, use FP mapping (all scalars in VEC)
299315
SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
300-
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
316+
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
301317

302318
// Finally construct the computed mapping.
303319
SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);

llvm/lib/Target/X86/GISel/X86RegisterBankInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class X86GenRegisterBankInfo : public RegisterBankInfo {
3232
static RegisterBankInfo::PartialMapping PartMappings[];
3333
static RegisterBankInfo::ValueMapping ValMappings[];
3434

35-
static PartialMappingIdx getPartialMappingIdx(const LLT &Ty, bool isFP);
35+
static PartialMappingIdx getPartialMappingIdx(const MachineInstr &MI,
36+
const LLT &Ty, bool isFP);
3637
static const RegisterBankInfo::ValueMapping *
3738
getValueMapping(PartialMappingIdx Idx, unsigned NumOperands);
3839
};

llvm/lib/Target/X86/X86GenRegisterBankInfo.def

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ RegisterBankInfo::PartialMapping X86GenRegisterBankInfo::PartMappings[]{
2525
{0, 128, X86::VECRRegBank}, // :6
2626
{0, 256, X86::VECRRegBank}, // :7
2727
{0, 512, X86::VECRRegBank}, // :8
28+
// RFP32/64/80
29+
{0, 32, X86::PSRRegBank}, // :9
30+
{0, 64, X86::PSRRegBank}, // :10
31+
{0, 80, X86::PSRRegBank}, // :11
2832
};
2933
#endif // GET_TARGET_REGBANK_INFO_IMPL
3034

@@ -39,7 +43,10 @@ enum PartialMappingIdx {
3943
PMI_FP64,
4044
PMI_VEC128,
4145
PMI_VEC256,
42-
PMI_VEC512
46+
PMI_VEC512,
47+
PMI_PSR32,
48+
PMI_PSR64,
49+
PMI_PSR80
4350
};
4451
#endif // GET_TARGET_REGBANK_INFO_CLASS
4552

@@ -61,6 +68,9 @@ RegisterBankInfo::ValueMapping X86GenRegisterBankInfo::ValMappings[]{
6168
INSTR_3OP(BREAKDOWN(PMI_VEC128, 1)) // 18: Vec128
6269
INSTR_3OP(BREAKDOWN(PMI_VEC256, 1)) // 21: Vec256
6370
INSTR_3OP(BREAKDOWN(PMI_VEC512, 1)) // 24: Vec512
71+
INSTR_3OP(BREAKDOWN(PMI_PSR32, 1)) // 25: Rfp32
72+
INSTR_3OP(BREAKDOWN(PMI_PSR64, 1)) // 26: Rfp64
73+
INSTR_3OP(BREAKDOWN(PMI_PSR80, 1)) // 27: Rfp80
6474
};
6575
#undef INSTR_3OP
6676
#undef BREAKDOWN
@@ -78,6 +88,9 @@ enum ValueMappingIdx {
7888
VMI_3OpsVec128Idx = PMI_VEC128 * 3,
7989
VMI_3OpsVec256Idx = PMI_VEC256 * 3,
8090
VMI_3OpsVec512Idx = PMI_VEC512 * 3,
91+
VMI_3OpsPs32Idx = PMI_PSR32 * 3,
92+
VMI_3OpsPs64Idx = PMI_PSR64 * 3,
93+
VMI_3OpsPs80Idx = PMI_PSR80 * 3,
8194
};
8295
#undef GET_TARGET_REGBANK_INFO_CLASS
8396
#endif // GET_TARGET_REGBANK_INFO_CLASS
@@ -89,7 +102,7 @@ X86GenRegisterBankInfo::getValueMapping(PartialMappingIdx Idx,
89102
unsigned NumOperands) {
90103

91104
// We can use VMI_3Ops Mapping for all the cases.
92-
if (NumOperands <= 3 && (Idx >= PMI_GPR8 && Idx <= PMI_VEC512))
105+
if (NumOperands <= 3 && (Idx >= PMI_GPR8 && Idx <= PMI_PSR80))
93106
return &ValMappings[(unsigned)Idx * 3];
94107

95108
llvm_unreachable("Unsupported PartialMappingIdx.");

llvm/lib/Target/X86/X86RegisterBanks.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ def GPRRegBank : RegisterBank<"GPR", [GR64]>;
1414

1515
/// Floating Point/Vector Registers
1616
def VECRRegBank : RegisterBank<"VECR", [VR512]>;
17+
18+
/// Pseudo Registers: RFP80
19+
def PSRRegBank : RegisterBank<"PSR", [RFP32, RFP64, RFP80]>;

0 commit comments

Comments
 (0)