[llvm] [RISCV][GISel] Add support for G_FCMP with F and D extensions. (PR #70624)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 9 15:09:05 PST 2023
================
@@ -836,6 +840,130 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
}
+// Convert an FCMP predicate to one of the supported F or D instructions.
+static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
+ assert((Size == 32 || Size == 64) && "Unsupported size");
+ switch (Pred) {
+ default:
+ llvm_unreachable("Unsupported predicate");
+ case CmpInst::FCMP_OLT:
+ return Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
+ case CmpInst::FCMP_OLE:
+ return Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
+ case CmpInst::FCMP_OEQ:
+ return Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
+ }
+}
+
+// Try legalizing an FCMP by swapping or inverting the predicate to one that
+// is supported.
+static bool legalizeFCmpPredicate(Register &LHS, Register &RHS,
+ CmpInst::Predicate &Pred, bool &NeedInvert) {
+ auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
+ return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
+ Pred == CmpInst::FCMP_OEQ;
+ };
+
+ assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
+
+ CmpInst::Predicate InvPred = CmpInst::getSwappedPredicate(Pred);
+ if (isLegalFCmpPredicate(InvPred)) {
+ Pred = InvPred;
+ std::swap(LHS, RHS);
+ return true;
+ }
+
+ InvPred = CmpInst::getInversePredicate(Pred);
+ NeedInvert = true;
+ if (isLegalFCmpPredicate(InvPred)) {
+ Pred = InvPred;
+ return true;
+ }
+ InvPred = CmpInst::getSwappedPredicate(InvPred);
+ if (isLegalFCmpPredicate(InvPred)) {
+ Pred = InvPred;
+ std::swap(LHS, RHS);
+ return true;
+ }
+
+ return false;
+}
+
+// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
+// the result in DstReg.
+// FIXME: Maybe we should expand this earlier.
+bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
+ MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const {
+ auto &CmpMI = cast<GFCmp>(MI);
+ CmpInst::Predicate Pred = CmpMI.getCond();
+
+ Register DstReg = CmpMI.getReg(0);
+ Register LHS = CmpMI.getLHSReg();
+ Register RHS = CmpMI.getRHSReg();
+
+ unsigned Size = MRI.getType(LHS).getSizeInBits();
+ assert((Size == 32 || Size == 64) && "Unexpected size");
+
+ Register TmpReg = DstReg;
+
+ bool NeedInvert = false;
+ // First try swapping operands or inverting.
+ if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
+ if (NeedInvert)
+ TmpReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ auto Cmp = MIB.buildInstr(getFCmpOpcode(Pred, Size), {TmpReg}, {LHS, RHS});
+ if (!Cmp.constrainAllUses(TII, TRI, RBI))
+ return false;
+ } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
+ // fcmp ogt LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
----------------
topperc wrote:
`fcmp one`?
https://github.com/llvm/llvm-project/pull/70624
More information about the llvm-commits
mailing list