[llvm] [AArch64] Legalize fp128 scalars as libcalls for G_FCMP (PR #98452)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 18 23:07:17 PDT 2024
================
@@ -980,6 +979,148 @@ LegalizerHelper::createSetStateLibcall(MachineIRBuilder &MIRBuilder,
LocObserver, nullptr);
}
+/// Returns the corresponding libcall for the given Pred and
+/// 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) {
+
+ switch (Pred) {
+ case CmpInst::FCMP_OEQ:
+ return {RTLIB::OEQ_F128, CmpInst::ICMP_EQ};
+ case CmpInst::FCMP_UNE:
+ return {RTLIB::UNE_F128, CmpInst::ICMP_NE};
+ case CmpInst::FCMP_OGE:
+ return {RTLIB::OGE_F128, CmpInst::ICMP_SGE};
+ case CmpInst::FCMP_OLT:
+ return {RTLIB::OLT_F128, CmpInst::ICMP_SLT};
+ case CmpInst::FCMP_OLE:
+ return {RTLIB::OLE_F128, CmpInst::ICMP_SLE};
+ case CmpInst::FCMP_OGT:
+ return {RTLIB::OGT_F128, CmpInst::ICMP_SGT};
+ case CmpInst::FCMP_UNO:
+ return {RTLIB::UO_F128, CmpInst::ICMP_NE};
+ default:
+ return {RTLIB::UNKNOWN_LIBCALL, CmpInst::BAD_ICMP_PREDICATE};
+ }
+}
+
+LegalizerHelper::LegalizeResult
+LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
+ MachineInstr &MI,
+ LostDebugLocObserver &LocObserver) {
+ auto &MF = MIRBuilder.getMF();
+ auto &Ctx = MF.getFunction().getContext();
+ const GFCmp *Cmp = cast<GFCmp>(&MI);
+
+ LLT OpLLT = MRI.getType(Cmp->getLHSReg());
+ if (OpLLT != LLT::scalar(128) || OpLLT != MRI.getType(Cmp->getRHSReg()))
+ return UnableToLegalize;
+
+ Type *OpType = getFloatTypeForLLT(Ctx, OpLLT);
+
+ // Libcall always return i32
+ constexpr LLT I32LLT = LLT::scalar(32);
+ constexpr LLT PredTy = LLT::scalar(1);
+
+ const Register DstReg = Cmp->getReg(0);
+ const Register Op1 = Cmp->getLHSReg();
+ const Register Op2 = Cmp->getRHSReg();
+ const auto Cond = Cmp->getCond();
+
+ // Generates a libcall followed by ICMP
+ const auto BuildLibcall = [&](const RTLIB::Libcall Libcall,
+ const CmpInst::Predicate ICmpPred) -> Register {
+ Register Temp = MRI.createGenericVirtualRegister(I32LLT);
+ // Generate libcall, storing result into Temp
+ const auto Status =
+ createLibcall(MIRBuilder, Libcall, {Temp, Type::getInt32Ty(Ctx), 0},
+ {{Op1, OpType, 0}, {Op2, OpType, 1}}, LocObserver, &MI);
+ if (!Status)
+ return {};
+
+ // FCMP libcall always returns an i32, we need to compare it with #0 to get
+ // the final result.
+ return MIRBuilder
+ .buildICmp(ICmpPred, PredTy, Temp, MIRBuilder.buildConstant(I32LLT, 0))
+ .getReg(0);
+ };
+
+ // Simple case if we have a direct mapping from predicate to libcall
+ if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond);
+ Libcall != RTLIB::UNKNOWN_LIBCALL &&
+ ICmpPred != CmpInst::BAD_ICMP_PREDICATE) {
+ if (const auto Res = BuildLibcall(Libcall, ICmpPred)) {
+ MIRBuilder.buildCopy(DstReg, Res);
----------------
davemgreen wrote:
If the type of the function is always an i32, might that need to be zext/sext/trunc to the predicate type?
https://github.com/llvm/llvm-project/pull/98452
More information about the llvm-commits
mailing list