Skip to content

Add support for x87 registers on GISel register selection #83528

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
merged 3 commits into from
Mar 5, 2024
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
13 changes: 8 additions & 5 deletions llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
bool HasVLX = Subtarget.hasVLX();
bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();
bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();
bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();

const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));
const LLT s1 = LLT::scalar(1);
Expand Down Expand Up @@ -415,17 +416,19 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
// fp constants
getActionDefinitionsBuilder(G_FCONSTANT)
.legalIf([=](const LegalityQuery &Query) -> bool {
return (HasSSE1 && typeInSet(0, {s32})(Query)) ||
(HasSSE2 && typeInSet(0, {s64})(Query));
return (typeInSet(0, {s32, s64})(Query)) ||
(UseX87 && typeInSet(0, {s80})(Query));
});

// fp arithmetic
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
.legalIf([=](const LegalityQuery &Query) {
return (HasSSE1 && typeInSet(0, {s32, v4s32})(Query)) ||
(HasSSE2 && typeInSet(0, {s64, v2s64})(Query)) ||
return (typeInSet(0, {s32, s64})(Query)) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing issue but I think this is an overly verbose way of expressing the simplest type of operation with a single type operand

(HasSSE1 && typeInSet(0, {v4s32})(Query)) ||
(HasSSE2 && typeInSet(0, {v2s64})(Query)) ||
(HasAVX && typeInSet(0, {v8s32, v4s64})(Query)) ||
(HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query));
(HasAVX512 && typeInSet(0, {v16s32, v8s64})(Query)) ||
(UseX87 && typeInSet(0, {s80})(Query));
});

// fp comparison
Expand Down
48 changes: 32 additions & 16 deletions llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "X86RegisterBankInfo.h"
#include "X86InstrInfo.h"
#include "X86Subtarget.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterBank.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
Expand Down Expand Up @@ -59,11 +60,24 @@ X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
X86::VR512RegClass.hasSubClassEq(&RC))
return getRegBank(X86::VECRRegBankID);

if (X86::RFP80RegClass.hasSubClassEq(&RC) ||
X86::RFP32RegClass.hasSubClassEq(&RC) ||
X86::RFP64RegClass.hasSubClassEq(&RC))
return getRegBank(X86::PSRRegBankID);

llvm_unreachable("Unsupported register kind yet.");
}

X86GenRegisterBankInfo::PartialMappingIdx
X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
X86GenRegisterBankInfo::getPartialMappingIdx(const MachineInstr &MI,
const LLT &Ty, bool isFP) {
const MachineFunction *MF = MI.getMF();
const X86Subtarget *ST = &MF->getSubtarget<X86Subtarget>();
bool HasSSE1 = ST->hasSSE1();
bool HasSSE2 = ST->hasSSE2();
// 80 bits is only generated for X87 floating points.
if (Ty.getSizeInBits() == 80)
isFP = true;
if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
switch (Ty.getSizeInBits()) {
case 1:
Expand All @@ -84,11 +98,13 @@ X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
} else if (Ty.isScalar()) {
switch (Ty.getSizeInBits()) {
case 32:
return PMI_FP32;
return HasSSE1 ? PMI_FP32 : PMI_PSR32;
case 64:
return PMI_FP64;
return HasSSE2 ? PMI_FP64 : PMI_PSR64;
case 128:
return PMI_VEC128;
case 80:
return PMI_PSR80;
default:
llvm_unreachable("Unsupported register size.");
}
Expand Down Expand Up @@ -118,7 +134,8 @@ void X86RegisterBankInfo::getInstrPartialMappingIdxs(
if (!MO.isReg() || !MO.getReg())
OpRegBankIdx[Idx] = PMI_None;
else
OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
OpRegBankIdx[Idx] =
getPartialMappingIdx(MI, MRI.getType(MO.getReg()), isFP);
}
}

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

auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, isFP), 3);
return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
}

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

auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, false), 3);
return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);

}
default:
break;
Expand All @@ -206,7 +222,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case TargetOpcode::G_FPTRUNC:
case TargetOpcode::G_FCONSTANT:
// Instruction having only floating-point operands (all scalars in VECRReg)
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
break;
case TargetOpcode::G_SITOFP:
case TargetOpcode::G_FPTOSI: {
Expand All @@ -219,8 +235,8 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {

bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);
OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ SecondArgIsFP);
break;
}
case TargetOpcode::G_FCMP: {
Expand All @@ -234,7 +250,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
(void)Size;
assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");

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

getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ isFPTrunc || isFPAnyExt,
OpRegBankIdx);
} break;
default:
// Track the bank of each register, use NotFP mapping (all scalars in GPRs)
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ false, OpRegBankIdx);
break;
}

Expand Down Expand Up @@ -288,16 +304,16 @@ X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
case TargetOpcode::G_LOAD:
case TargetOpcode::G_STORE:
case TargetOpcode::G_IMPLICIT_DEF: {
// we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
// we going to try to map 32/64/80 bit to PMI_FP32/PMI_FP64/PMI_FP80
unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
if (Size != 32 && Size != 64)
if (Size != 32 && Size != 64 && Size != 80)
break;

unsigned NumOperands = MI.getNumOperands();

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

// Finally construct the computed mapping.
SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/X86/GISel/X86RegisterBankInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class X86GenRegisterBankInfo : public RegisterBankInfo {
static RegisterBankInfo::PartialMapping PartMappings[];
static RegisterBankInfo::ValueMapping ValMappings[];

static PartialMappingIdx getPartialMappingIdx(const LLT &Ty, bool isFP);
static PartialMappingIdx getPartialMappingIdx(const MachineInstr &MI,
const LLT &Ty, bool isFP);
static const RegisterBankInfo::ValueMapping *
getValueMapping(PartialMappingIdx Idx, unsigned NumOperands);
};
Expand Down
17 changes: 15 additions & 2 deletions llvm/lib/Target/X86/X86GenRegisterBankInfo.def
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ RegisterBankInfo::PartialMapping X86GenRegisterBankInfo::PartMappings[]{
{0, 128, X86::VECRRegBank}, // :6
{0, 256, X86::VECRRegBank}, // :7
{0, 512, X86::VECRRegBank}, // :8
// RFP32/64/80
{0, 32, X86::PSRRegBank}, // :9
{0, 64, X86::PSRRegBank}, // :10
{0, 80, X86::PSRRegBank}, // :11
};
#endif // GET_TARGET_REGBANK_INFO_IMPL

Expand All @@ -39,7 +43,10 @@ enum PartialMappingIdx {
PMI_FP64,
PMI_VEC128,
PMI_VEC256,
PMI_VEC512
PMI_VEC512,
PMI_PSR32,
PMI_PSR64,
PMI_PSR80
};
#endif // GET_TARGET_REGBANK_INFO_CLASS

Expand All @@ -61,6 +68,9 @@ RegisterBankInfo::ValueMapping X86GenRegisterBankInfo::ValMappings[]{
INSTR_3OP(BREAKDOWN(PMI_VEC128, 1)) // 18: Vec128
INSTR_3OP(BREAKDOWN(PMI_VEC256, 1)) // 21: Vec256
INSTR_3OP(BREAKDOWN(PMI_VEC512, 1)) // 24: Vec512
INSTR_3OP(BREAKDOWN(PMI_PSR32, 1)) // 25: Rfp32
INSTR_3OP(BREAKDOWN(PMI_PSR64, 1)) // 26: Rfp64
INSTR_3OP(BREAKDOWN(PMI_PSR80, 1)) // 27: Rfp80
};
#undef INSTR_3OP
#undef BREAKDOWN
Expand All @@ -78,6 +88,9 @@ enum ValueMappingIdx {
VMI_3OpsVec128Idx = PMI_VEC128 * 3,
VMI_3OpsVec256Idx = PMI_VEC256 * 3,
VMI_3OpsVec512Idx = PMI_VEC512 * 3,
VMI_3OpsPs32Idx = PMI_PSR32 * 3,
VMI_3OpsPs64Idx = PMI_PSR64 * 3,
VMI_3OpsPs80Idx = PMI_PSR80 * 3,
};
#undef GET_TARGET_REGBANK_INFO_CLASS
#endif // GET_TARGET_REGBANK_INFO_CLASS
Expand All @@ -89,7 +102,7 @@ X86GenRegisterBankInfo::getValueMapping(PartialMappingIdx Idx,
unsigned NumOperands) {

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

llvm_unreachable("Unsupported PartialMappingIdx.");
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86RegisterBanks.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ def GPRRegBank : RegisterBank<"GPR", [GR64]>;

/// Floating Point/Vector Registers
def VECRRegBank : RegisterBank<"VECR", [VR512]>;

/// Pseudo Registers: RFP80
def PSRRegBank : RegisterBank<"PSR", [RFP32, RFP64, RFP80]>;
Loading