@@ -4748,6 +4748,9 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
47484748 case G_FMINIMUMNUM:
47494749 case G_FMAXIMUMNUM:
47504750 return lowerFMinNumMaxNum (MI);
4751+ case G_FMINIMUM:
4752+ case G_FMAXIMUM:
4753+ return lowerFMinimumMaximum (MI);
47514754 case G_MERGE_VALUES:
47524755 return lowerMergeValues (MI);
47534756 case G_UNMERGE_VALUES:
@@ -8777,6 +8780,77 @@ LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
87778780 return Legalized;
87788781}
87798782
8783+ LegalizerHelper::LegalizeResult
8784+ LegalizerHelper::lowerFMinimumMaximum (MachineInstr &MI) {
8785+ unsigned Opc = MI.getOpcode ();
8786+ auto [Dst, Src0, Src1] = MI.getFirst3Regs ();
8787+ LLT Ty = MRI.getType (Dst);
8788+ LLT CmpTy = Ty.changeElementSize (1 );
8789+
8790+ bool IsMax = (Opc == TargetOpcode::G_FMAXIMUM);
8791+ unsigned OpcIeee =
8792+ IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8793+ unsigned OpcNonIeee =
8794+ IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8795+ bool MinMaxMustRespectOrderedZero = false ;
8796+ Register Res;
8797+
8798+ // IEEE variants don't need canonicalization
8799+ if (LI.isLegalOrCustom ({OpcIeee, Ty})) {
8800+ Res = MIRBuilder.buildInstr (OpcIeee, {Ty}, {Src0, Src1}).getReg (0 );
8801+ MinMaxMustRespectOrderedZero = true ;
8802+ } else if (LI.isLegalOrCustom ({OpcNonIeee, Ty})) {
8803+ Res = MIRBuilder.buildInstr (OpcNonIeee, {Ty}, {Src0, Src1}).getReg (0 );
8804+ } else {
8805+ auto Compare = MIRBuilder.buildFCmp (
8806+ IsMax ? CmpInst::FCMP_OGT : CmpInst::FCMP_OLT, CmpTy, Src0, Src1);
8807+ Res = MIRBuilder.buildSelect (Ty, Compare, Src0, Src1).getReg (0 );
8808+ }
8809+
8810+ // Propagate any NaN of both operands
8811+ if (!MI.getFlag (MachineInstr::FmNoNans) &&
8812+ (!isKnownNeverNaN (Src0, MRI) || isKnownNeverNaN (Src1, MRI))) {
8813+ auto IsOrdered = MIRBuilder.buildFCmp (CmpInst::FCMP_ORD, CmpTy, Src0, Src1);
8814+
8815+ LLT ElementTy = Ty.isScalar () ? Ty : Ty.getElementType ();
8816+ APFloat NaNValue = APFloat::getNaN (getFltSemanticForLLT (ElementTy));
8817+ Register NaN = MIRBuilder.buildFConstant (ElementTy, NaNValue).getReg (0 );
8818+ if (Ty.isVector ())
8819+ NaN = MIRBuilder.buildSplatBuildVector (Ty, NaN).getReg (0 );
8820+
8821+ Res = MIRBuilder.buildSelect (Ty, IsOrdered, Res, NaN).getReg (0 );
8822+ }
8823+
8824+ // fminimum/fmaximum requires -0.0 less than +0.0
8825+ if (!MinMaxMustRespectOrderedZero && !MI.getFlag (MachineInstr::FmNsz)) {
8826+ GISelValueTracking VT (MIRBuilder.getMF ());
8827+ KnownFPClass Src0Info = VT.computeKnownFPClass (Src0, fcZero);
8828+ KnownFPClass Src1Info = VT.computeKnownFPClass (Src1, fcZero);
8829+
8830+ if (!Src0Info.isKnownNeverZero () && !Src1Info.isKnownNeverZero ()) {
8831+ const unsigned Flags = MI.getFlags ();
8832+ Register Zero = MIRBuilder.buildFConstant (Ty, 0.0 ).getReg (0 );
8833+ auto IsZero = MIRBuilder.buildFCmp (CmpInst::FCMP_OEQ, CmpTy, Res, Zero);
8834+
8835+ unsigned TestClass = IsMax ? fcPosZero : fcNegZero;
8836+
8837+ auto LHSTestZero = MIRBuilder.buildIsFPClass (CmpTy, Src0, TestClass);
8838+ auto LHSSelect =
8839+ MIRBuilder.buildSelect (Ty, LHSTestZero, Src0, Res, Flags);
8840+
8841+ auto RHSTestZero = MIRBuilder.buildIsFPClass (CmpTy, Src1, TestClass);
8842+ auto RHSSelect =
8843+ MIRBuilder.buildSelect (Ty, RHSTestZero, Src1, LHSSelect, Flags);
8844+
8845+ Res = MIRBuilder.buildSelect (Ty, IsZero, RHSSelect, Res, Flags).getReg (0 );
8846+ }
8847+ }
8848+
8849+ MIRBuilder.buildCopy (Dst, Res);
8850+ MI.eraseFromParent ();
8851+ return Legalized;
8852+ }
8853+
87808854LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMad (MachineInstr &MI) {
87818855 // Expand G_FMAD a, b, c -> G_FADD (G_FMUL a, b), c
87828856 Register DstReg = MI.getOperand (0 ).getReg ();
0 commit comments