Skip to content

Commit 43b6b78

Browse files
authored
[RISCV][GISel] Use libcalls for f32/f64 G_FCMP without F/D extensions. (#117660)
LegalizerHelp only supported f128 libcalls and incorrectly assumed that the destination register for the G_FCMP was s32.
1 parent a94cec5 commit 43b6b78

File tree

4 files changed

+1227
-23
lines changed

4 files changed

+1227
-23
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,23 +1003,36 @@ LegalizerHelper::createSetStateLibcall(MachineIRBuilder &MIRBuilder,
10031003
/// the ICMP predicate that should be generated to compare with #0
10041004
/// after the libcall.
10051005
static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1006-
getFCMPLibcallDesc(const CmpInst::Predicate Pred) {
1006+
getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size) {
1007+
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1008+
do { \
1009+
switch (Size) { \
1010+
case 32: \
1011+
return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1012+
case 64: \
1013+
return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1014+
case 128: \
1015+
return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1016+
default: \
1017+
llvm_unreachable("unexpected size"); \
1018+
} \
1019+
} while (0)
10071020

10081021
switch (Pred) {
10091022
case CmpInst::FCMP_OEQ:
1010-
return {RTLIB::OEQ_F128, CmpInst::ICMP_EQ};
1023+
RTLIBCASE_CMP(OEQ_F, CmpInst::ICMP_EQ);
10111024
case CmpInst::FCMP_UNE:
1012-
return {RTLIB::UNE_F128, CmpInst::ICMP_NE};
1025+
RTLIBCASE_CMP(UNE_F, CmpInst::ICMP_NE);
10131026
case CmpInst::FCMP_OGE:
1014-
return {RTLIB::OGE_F128, CmpInst::ICMP_SGE};
1027+
RTLIBCASE_CMP(OGE_F, CmpInst::ICMP_SGE);
10151028
case CmpInst::FCMP_OLT:
1016-
return {RTLIB::OLT_F128, CmpInst::ICMP_SLT};
1029+
RTLIBCASE_CMP(OLT_F, CmpInst::ICMP_SLT);
10171030
case CmpInst::FCMP_OLE:
1018-
return {RTLIB::OLE_F128, CmpInst::ICMP_SLE};
1031+
RTLIBCASE_CMP(OLE_F, CmpInst::ICMP_SLE);
10191032
case CmpInst::FCMP_OGT:
1020-
return {RTLIB::OGT_F128, CmpInst::ICMP_SGT};
1033+
RTLIBCASE_CMP(OGT_F, CmpInst::ICMP_SGT);
10211034
case CmpInst::FCMP_UNO:
1022-
return {RTLIB::UO_F128, CmpInst::ICMP_NE};
1035+
RTLIBCASE_CMP(UO_F, CmpInst::ICMP_NE);
10231036
default:
10241037
return {RTLIB::UNKNOWN_LIBCALL, CmpInst::BAD_ICMP_PREDICATE};
10251038
}
@@ -1034,21 +1047,24 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
10341047
const GFCmp *Cmp = cast<GFCmp>(&MI);
10351048

10361049
LLT OpLLT = MRI.getType(Cmp->getLHSReg());
1037-
if (OpLLT != LLT::scalar(128) || OpLLT != MRI.getType(Cmp->getRHSReg()))
1050+
unsigned Size = OpLLT.getSizeInBits();
1051+
if ((Size != 32 && Size != 64 && Size != 128) ||
1052+
OpLLT != MRI.getType(Cmp->getRHSReg()))
10381053
return UnableToLegalize;
10391054

10401055
Type *OpType = getFloatTypeForLLT(Ctx, OpLLT);
10411056

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

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

10691085
// Simple case if we have a direct mapping from predicate to libcall
1070-
if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond);
1086+
if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond, Size);
10711087
Libcall != RTLIB::UNKNOWN_LIBCALL &&
10721088
ICmpPred != CmpInst::BAD_ICMP_PREDICATE) {
10731089
if (BuildLibcall(Libcall, ICmpPred, DstReg)) {
@@ -1083,11 +1099,13 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
10831099
// FCMP_UEQ: unordered or equal
10841100
// Convert into (FCMP_OEQ || FCMP_UNO).
10851101

1086-
const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
1087-
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred);
1102+
const auto [OeqLibcall, OeqPred] =
1103+
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
1104+
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
10881105

1089-
const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
1090-
const auto Uno = BuildLibcall(UnoLibcall, UnoPred);
1106+
const auto [UnoLibcall, UnoPred] =
1107+
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
1108+
const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
10911109
if (Oeq && Uno)
10921110
MIRBuilder.buildOr(DstReg, Oeq, Uno);
10931111
else
@@ -1102,13 +1120,15 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
11021120
// We inverse the predicate instead of generating a NOT
11031121
// to save one instruction.
11041122
// On AArch64 isel can even select two cmp into a single ccmp.
1105-
const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
1123+
const auto [OeqLibcall, OeqPred] =
1124+
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
11061125
const auto NotOeq =
1107-
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred));
1126+
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred), DstTy);
11081127

1109-
const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
1128+
const auto [UnoLibcall, UnoPred] =
1129+
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
11101130
const auto NotUno =
1111-
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred));
1131+
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred), DstTy);
11121132

11131133
if (NotOeq && NotUno)
11141134
MIRBuilder.buildAnd(DstReg, NotOeq, NotUno);
@@ -1130,7 +1150,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
11301150
// MIRBuilder.buildFCmp(CmpInst::getInversePredicate(Pred), PredTy,
11311151
// Op1, Op2));
11321152
const auto [InversedLibcall, InversedPred] =
1133-
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond));
1153+
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond), Size);
11341154
if (!BuildLibcall(InversedLibcall,
11351155
CmpInst::getInversePredicate(InversedPred), DstReg))
11361156
return UnableToLegalize;

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
530530
.legalFor(ST.hasStdExtF(), {{sXLen, s32}})
531531
.legalFor(ST.hasStdExtD(), {{sXLen, s64}})
532532
.legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
533-
.clampScalar(ST.hasStdExtF(), 0, sXLen, sXLen);
533+
.clampScalar(0, sXLen, sXLen)
534+
.libcallFor({{sXLen, s32}, {sXLen, s64}});
534535

535536
// TODO: Support vector version of G_IS_FPCLASS.
536537
getActionDefinitionsBuilder(G_IS_FPCLASS)

0 commit comments

Comments
 (0)