@@ -4674,6 +4674,9 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
46744674 case G_FMINIMUMNUM:
46754675 case G_FMAXIMUMNUM:
46764676 return lowerFMinNumMaxNum (MI);
4677+ case G_FMINIMUM:
4678+ case G_FMAXIMUM:
4679+ return lowerFMinimumMaximum (MI);
46774680 case G_MERGE_VALUES:
46784681 return lowerMergeValues (MI);
46794682 case G_UNMERGE_VALUES:
@@ -8294,6 +8297,75 @@ LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
82948297 return Legalized;
82958298}
82968299
8300+ LegalizerHelper::LegalizeResult
8301+ LegalizerHelper::lowerFMinimumMaximum (MachineInstr &MI) {
8302+ unsigned Opc = MI.getOpcode ();
8303+ auto [Dst, Src0, Src1] = MI.getFirst3Regs ();
8304+ LLT Ty = MRI.getType (Dst);
8305+ LLT CmpTy =
8306+ Ty.isScalar () ? LLT::scalar (1 ) : LLT::vector (Ty.getElementCount (), 1 );
8307+
8308+ bool IsMax = (Opc == TargetOpcode::G_FMAXIMUM);
8309+ unsigned OpcIeee =
8310+ IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8311+ unsigned OpcNonIeee =
8312+ IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8313+ bool MinMaxMustRespectOrderedZero = false ;
8314+ Register Res;
8315+
8316+ // IEEE variants don't need canonicalization
8317+ if (LI.isLegalOrCustom ({OpcIeee, Ty})) {
8318+ Res = MIRBuilder.buildInstr (OpcIeee, {Ty}, {Src0, Src1}).getReg (0 );
8319+ MinMaxMustRespectOrderedZero = true ;
8320+ } else if (LI.isLegalOrCustom ({OpcNonIeee, Ty})) {
8321+ Res = MIRBuilder.buildInstr (OpcNonIeee, {Ty}, {Src0, Src1}).getReg (0 );
8322+ } else {
8323+ auto Compare = MIRBuilder.buildFCmp (
8324+ IsMax ? CmpInst::FCMP_OGT : CmpInst::FCMP_OLT, CmpTy, Src0, Src1);
8325+ Res = MIRBuilder.buildSelect (Ty, Compare, Src0, Src1).getReg (0 );
8326+ }
8327+
8328+ // Propagate any NaN of both operands
8329+ if (!MI.getFlag (MachineInstr::FmNoNans) &&
8330+ (!isKnownNeverNaN (Src0, MRI) || isKnownNeverNaN (Src1, MRI))) {
8331+ auto IsOrdered = MIRBuilder.buildFCmp (CmpInst::FCMP_ORD, CmpTy, Src0, Src1);
8332+
8333+ LLT ElementTy = Ty.isScalar () ? Ty : Ty.getElementType ();
8334+ APFloat NaNValue = APFloat::getNaN (getFltSemanticForLLT (ElementTy));
8335+ Register NaN = MIRBuilder.buildFConstant (ElementTy, NaNValue).getReg (0 );
8336+ if (Ty.isVector ())
8337+ NaN = MIRBuilder.buildSplatBuildVector (Ty, NaN).getReg (0 );
8338+
8339+ Res = MIRBuilder.buildSelect (Ty, IsOrdered, Res, NaN).getReg (0 );
8340+ }
8341+
8342+ // fminimum/fmaximum requires -0.0 less than +0.0
8343+ if (!MinMaxMustRespectOrderedZero && !MI.getFlag (MachineInstr::FmNsz)) {
8344+ GISelValueTracking VT (MIRBuilder.getMF ());
8345+ KnownFPClass Src0Info = VT.computeKnownFPClass (Src0, fcZero);
8346+ KnownFPClass Src1Info = VT.computeKnownFPClass (Src1, fcZero);
8347+
8348+ if (!Src0Info.isKnownNeverZero () && !Src1Info.isKnownNeverZero ()) {
8349+ Register Zero = MIRBuilder.buildFConstant (Ty, 0.0 ).getReg (0 );
8350+ auto IsZero = MIRBuilder.buildFCmp (CmpInst::FCMP_OEQ, CmpTy, Res, Zero);
8351+
8352+ unsigned TestClass = IsMax ? fcPosZero : fcNegZero;
8353+
8354+ auto LHSTestZero = MIRBuilder.buildIsFPClass (CmpTy, Src0, TestClass);
8355+ auto LHSSelect = MIRBuilder.buildSelect (Ty, LHSTestZero, Src0, Res);
8356+
8357+ auto RHSTestZero = MIRBuilder.buildIsFPClass (CmpTy, Src1, TestClass);
8358+ auto RHSSelect = MIRBuilder.buildSelect (Ty, RHSTestZero, Src1, LHSSelect);
8359+
8360+ Res = MIRBuilder.buildSelect (Ty, IsZero, RHSSelect, Res).getReg (0 );
8361+ }
8362+ }
8363+
8364+ MIRBuilder.buildCopy (Dst, Res);
8365+ MI.eraseFromParent ();
8366+ return Legalized;
8367+ }
8368+
82978369LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMad (MachineInstr &MI) {
82988370 // Expand G_FMAD a, b, c -> G_FADD (G_FMUL a, b), c
82998371 Register DstReg = MI.getOperand (0 ).getReg ();
0 commit comments