Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
64 changes: 42 additions & 22 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,23 +1001,36 @@ LegalizerHelper::createSetStateLibcall(MachineIRBuilder &MIRBuilder,
/// the ICMP predicate that should be generated to compare with #0
/// after the libcall.
static std::pair<RTLIB::Libcall, CmpInst::Predicate>
getFCMPLibcallDesc(const CmpInst::Predicate Pred) {
getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size) {
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
do { \
switch (Size) { \
case 32: \
return {RTLIB::LibcallPrefix##32, ICmpPred}; \
case 64: \
return {RTLIB::LibcallPrefix##64, ICmpPred}; \
case 128: \
return {RTLIB::LibcallPrefix##128, ICmpPred}; \
default: \
llvm_unreachable("unexpected size"); \
} \
} while (0)

switch (Pred) {
case CmpInst::FCMP_OEQ:
return {RTLIB::OEQ_F128, CmpInst::ICMP_EQ};
RTLIBCASE_CMP(OEQ_F, CmpInst::ICMP_EQ);
case CmpInst::FCMP_UNE:
return {RTLIB::UNE_F128, CmpInst::ICMP_NE};
RTLIBCASE_CMP(UNE_F, CmpInst::ICMP_NE);
case CmpInst::FCMP_OGE:
return {RTLIB::OGE_F128, CmpInst::ICMP_SGE};
RTLIBCASE_CMP(OGE_F, CmpInst::ICMP_SGE);
case CmpInst::FCMP_OLT:
return {RTLIB::OLT_F128, CmpInst::ICMP_SLT};
RTLIBCASE_CMP(OLT_F, CmpInst::ICMP_SLT);
case CmpInst::FCMP_OLE:
return {RTLIB::OLE_F128, CmpInst::ICMP_SLE};
RTLIBCASE_CMP(OLE_F, CmpInst::ICMP_SLE);
case CmpInst::FCMP_OGT:
return {RTLIB::OGT_F128, CmpInst::ICMP_SGT};
RTLIBCASE_CMP(OGT_F, CmpInst::ICMP_SGT);
case CmpInst::FCMP_UNO:
return {RTLIB::UO_F128, CmpInst::ICMP_NE};
RTLIBCASE_CMP(UO_F, CmpInst::ICMP_NE);
default:
return {RTLIB::UNKNOWN_LIBCALL, CmpInst::BAD_ICMP_PREDICATE};
}
Expand All @@ -1032,21 +1045,24 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
const GFCmp *Cmp = cast<GFCmp>(&MI);

LLT OpLLT = MRI.getType(Cmp->getLHSReg());
if (OpLLT != LLT::scalar(128) || OpLLT != MRI.getType(Cmp->getRHSReg()))
unsigned Size = OpLLT.getSizeInBits();
if ((Size != 32 && Size != 64 && Size != 128) ||
OpLLT != MRI.getType(Cmp->getRHSReg()))
return UnableToLegalize;

Type *OpType = getFloatTypeForLLT(Ctx, OpLLT);

// DstReg type is s32
const Register DstReg = Cmp->getReg(0);
LLT DstTy = MRI.getType(DstReg);
const auto Cond = Cmp->getCond();

// Reference:
// https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Comparison-functions-1
// Generates a libcall followed by ICMP.
const auto BuildLibcall =
[&](const RTLIB::Libcall Libcall, const CmpInst::Predicate ICmpPred,
const DstOp &Res = LLT::scalar(32)) -> Register {
const auto BuildLibcall = [&](const RTLIB::Libcall Libcall,
const CmpInst::Predicate ICmpPred,
const DstOp &Res) -> Register {
// FCMP libcall always returns an i32, and needs an ICMP with #0.
constexpr LLT TempLLT = LLT::scalar(32);
Register Temp = MRI.createGenericVirtualRegister(TempLLT);
Expand All @@ -1065,7 +1081,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
};

// Simple case if we have a direct mapping from predicate to libcall
if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond);
if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond, Size);
Libcall != RTLIB::UNKNOWN_LIBCALL &&
ICmpPred != CmpInst::BAD_ICMP_PREDICATE) {
if (BuildLibcall(Libcall, ICmpPred, DstReg)) {
Expand All @@ -1081,11 +1097,13 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
// FCMP_UEQ: unordered or equal
// Convert into (FCMP_OEQ || FCMP_UNO).

const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred);
const auto [OeqLibcall, OeqPred] =
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);

const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
const auto Uno = BuildLibcall(UnoLibcall, UnoPred);
const auto [UnoLibcall, UnoPred] =
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
if (Oeq && Uno)
MIRBuilder.buildOr(DstReg, Oeq, Uno);
else
Expand All @@ -1100,13 +1118,15 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
// We inverse the predicate instead of generating a NOT
// to save one instruction.
// On AArch64 isel can even select two cmp into a single ccmp.
const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
const auto [OeqLibcall, OeqPred] =
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
const auto NotOeq =
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred));
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred), DstTy);

const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
const auto [UnoLibcall, UnoPred] =
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
const auto NotUno =
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred));
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred), DstTy);

if (NotOeq && NotUno)
MIRBuilder.buildAnd(DstReg, NotOeq, NotUno);
Expand All @@ -1128,7 +1148,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
// MIRBuilder.buildFCmp(CmpInst::getInversePredicate(Pred), PredTy,
// Op1, Op2));
const auto [InversedLibcall, InversedPred] =
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond));
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond), Size);
if (!BuildLibcall(InversedLibcall,
CmpInst::getInversePredicate(InversedPred), DstReg))
return UnableToLegalize;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
.legalFor(ST.hasStdExtF(), {{sXLen, s32}})
.legalFor(ST.hasStdExtD(), {{sXLen, s64}})
.legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
.clampScalar(ST.hasStdExtF(), 0, sXLen, sXLen);
.clampScalar(0, sXLen, sXLen)
.libcallFor({{sXLen, s32}, {sXLen, s64}});

// TODO: Support vector version of G_IS_FPCLASS.
getActionDefinitionsBuilder(G_IS_FPCLASS)
Expand Down
Loading
Loading