Skip to content

Commit 4a6235b

Browse files
committed
[RISCV][GISel] Use libcalls for f32/f64 G_FCMP without F/D extensions.
LegalizerHelp only supported f128 libcalls and incorrectly assumed that the destination register for the G_FCMP was s32.
1 parent 2ed8c5d commit 4a6235b

File tree

4 files changed

+1196
-23
lines changed

4 files changed

+1196
-23
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

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

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

10341047
LLT OpLLT = MRI.getType(Cmp->getLHSReg());
1035-
if (OpLLT != LLT::scalar(128) || OpLLT != MRI.getType(Cmp->getRHSReg()))
1048+
unsigned Size = OpLLT.getSizeInBits();
1049+
if ((Size != 32 && Size != 64 && Size != 128) ||
1050+
OpLLT != MRI.getType(Cmp->getRHSReg()))
10361051
return UnableToLegalize;
10371052

10381053
Type *OpType = getFloatTypeForLLT(Ctx, OpLLT);
10391054

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

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

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

1084-
const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
1085-
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred);
1100+
const auto [OeqLibcall, OeqPred] =
1101+
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
1102+
const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
10861103

1087-
const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
1088-
const auto Uno = BuildLibcall(UnoLibcall, UnoPred);
1104+
const auto [UnoLibcall, UnoPred] =
1105+
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
1106+
const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
10891107
if (Oeq && Uno)
10901108
MIRBuilder.buildOr(DstReg, Oeq, Uno);
10911109
else
@@ -1100,13 +1118,15 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
11001118
// We inverse the predicate instead of generating a NOT
11011119
// to save one instruction.
11021120
// On AArch64 isel can even select two cmp into a single ccmp.
1103-
const auto [OeqLibcall, OeqPred] = getFCMPLibcallDesc(CmpInst::FCMP_OEQ);
1121+
const auto [OeqLibcall, OeqPred] =
1122+
getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
11041123
const auto NotOeq =
1105-
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred));
1124+
BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred), DstTy);
11061125

1107-
const auto [UnoLibcall, UnoPred] = getFCMPLibcallDesc(CmpInst::FCMP_UNO);
1126+
const auto [UnoLibcall, UnoPred] =
1127+
getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
11081128
const auto NotUno =
1109-
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred));
1129+
BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred), DstTy);
11101130

11111131
if (NotOeq && NotUno)
11121132
MIRBuilder.buildAnd(DstReg, NotOeq, NotUno);
@@ -1128,7 +1148,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
11281148
// MIRBuilder.buildFCmp(CmpInst::getInversePredicate(Pred), PredTy,
11291149
// Op1, Op2));
11301150
const auto [InversedLibcall, InversedPred] =
1131-
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond));
1151+
getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond), Size);
11321152
if (!BuildLibcall(InversedLibcall,
11331153
CmpInst::getInversePredicate(InversedPred), DstReg))
11341154
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)