@@ -456,7 +456,13 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
456
456
setOperationAction (ISD::FMA, MVT::f64 , Expand);
457
457
setOperationAction (ISD::FREM, MVT::f32 , Expand);
458
458
setOperationAction (ISD::FREM, MVT::f64 , Expand);
459
-
459
+ if (Subtarget.isFP64bit () || Subtarget.isSingleFloat () ||
460
+ Subtarget.isFPXX ()) {
461
+ setOperationAction (ISD::FMINIMUM, MVT::f32 , Custom);
462
+ setOperationAction (ISD::FMAXIMUM, MVT::f32 , Custom);
463
+ setOperationAction (ISD::FMINIMUM, MVT::f64 , Custom);
464
+ setOperationAction (ISD::FMAXIMUM, MVT::f64 , Custom);
465
+ }
460
466
// Lower f16 conversion operations into library calls
461
467
setOperationAction (ISD::FP16_TO_FP, MVT::f32 , Expand);
462
468
setOperationAction (ISD::FP_TO_FP16, MVT::f32 , Expand);
@@ -1267,6 +1273,9 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
1267
1273
case ISD::STORE: return lowerSTORE (Op, DAG);
1268
1274
case ISD::EH_DWARF_CFA: return lowerEH_DWARF_CFA (Op, DAG);
1269
1275
case ISD::FP_TO_SINT: return lowerFP_TO_SINT (Op, DAG);
1276
+ case ISD::FMINIMUM:
1277
+ case ISD::FMAXIMUM:
1278
+ return lowerFMINIMUM_FMAXIMUM (Op, DAG);
1270
1279
}
1271
1280
return SDValue ();
1272
1281
}
@@ -2525,6 +2534,94 @@ SDValue MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const {
2525
2534
return lowerFABS32 (Op, DAG, Subtarget.hasExtractInsert ());
2526
2535
}
2527
2536
2537
+ SDValue MipsTargetLowering::lowerFMINIMUM_FMAXIMUM (SDValue Op,
2538
+ SelectionDAG &DAG) const {
2539
+ // Get information about X and Y:
2540
+ // VT of the operand, the operand itself and its length,
2541
+ // The possibility of X or Y being a NaN.
2542
+ EVT VT = Op.getValueType ();
2543
+ assert (
2544
+ (VT == MVT::f32 || VT == MVT::f64 ) &&
2545
+ " Unsupported float point type or operands are not floating point values" );
2546
+ // Used to compare an operand to zero.
2547
+ EVT IVT = VT.changeTypeToInteger ();
2548
+ // Whether it is fminimum or fmaximum.
2549
+ ISD::NodeType CmpOp = (ISD::NodeType)Op->getOpcode ();
2550
+ bool IsMaxOp = (CmpOp == ISD::FMAXIMUM);
2551
+ SDValue X = Op->getOperand (0 );
2552
+ SDValue Y = Op->getOperand (1 );
2553
+ // The constructed DAG.
2554
+ SDValue MinMax;
2555
+ // Location of current node.
2556
+ SDLoc Loc (Op);
2557
+ // VT for the usage of SETCC op.
2558
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo ();
2559
+ EVT SetCCType =
2560
+ TLI.getSetCCResultType (DAG.getDataLayout (), *DAG.getContext (), VT);
2561
+
2562
+ bool IsXNeverNaN = DAG.isKnownNeverNaN (X);
2563
+ bool IsYNeverNaN = DAG.isKnownNeverNaN (Y);
2564
+ bool NaNMightPresent = (!IsXNeverNaN || !IsYNeverNaN);
2565
+ bool IsXNeverZero = DAG.isKnownNeverZeroFloat (X);
2566
+ bool IsYNeverZero = DAG.isKnownNeverZeroFloat (Y);
2567
+ bool ZeroMightPresent = (!IsXNeverZero || !IsYNeverZero);
2568
+ // Note that on Pre-R6 targets fmin and fmax will be replaced with SetCC.
2569
+ if (Subtarget.hasMips32r6 () || Subtarget.hasMips64r6 ()) {
2570
+ // We have matched min.s/d and max.s/d to their corresponding SDAG
2571
+ // operations.
2572
+ MinMax =
2573
+ DAG.getNode ((IsMaxOp ? ISD::FMAXNUM : ISD::FMINNUM), Loc, VT, X, Y);
2574
+ } else {
2575
+ // Otherwise, use SETCC.
2576
+ SDValue SetCCCmp =
2577
+ DAG.getSetCC (Loc, SetCCType, X, Y,
2578
+ IsMaxOp ? ISD::CondCode::SETGT : ISD::CondCode::SETLT);
2579
+ MinMax = DAG.getSelect (Loc, VT, SetCCCmp, X, Y);
2580
+ }
2581
+ // Add NaN related checks.
2582
+ if (NaNMightPresent) {
2583
+ // If either X or Y is NaN, return NaN.
2584
+ APFloat APNaN = APFloat::getNaN (DAG.EVTToAPFloatSemantics (VT));
2585
+ SDValue TstNaN = DAG.getSetCC (Loc, SetCCType, X, Y, ISD::CondCode::SETUO);
2586
+ MinMax = DAG.getSelect (Loc, VT, TstNaN, DAG.getConstantFP (APNaN, Loc, VT),
2587
+ MinMax);
2588
+ }
2589
+ // Add zero related checks.
2590
+ if (ZeroMightPresent) {
2591
+ // Check if both X and Y are zeroes.
2592
+ // MIPS ignores signage of zeroes when comparing against zeroes, so -0.0 ==
2593
+ // +0.0.
2594
+ APFloat FPZero = APFloat::getZero (DAG.EVTToAPFloatSemantics (VT));
2595
+ SDValue ConstFPZero = DAG.getConstantFP (FPZero, Loc, VT);
2596
+ SDValue Res = DAG.getNode (ISD::FADD, Loc, VT, X, Y);
2597
+ SDValue TstZeroes =
2598
+ DAG.getSetCC (Loc, SetCCType, Res, ConstFPZero, ISD::CondCode::SETEQ);
2599
+ SDValue IsXSigned;
2600
+
2601
+ if (VT.getSizeInBits () == 64 && Subtarget.isGP32bit ()) {
2602
+ // Extract the higher 32 bits, and compare like how 64-bit does.
2603
+ SDValue ConstInt32Zero = DAG.getConstant (0 , Loc, MVT::i32 );
2604
+ SDValue XHiInt = DAG.getNode (MipsISD::ExtractElementF64, Loc, MVT::i32 , X,
2605
+ DAG.getConstant (1 , Loc, MVT::i32 ));
2606
+ IsXSigned = DAG.getSetCC (Loc, SetCCType, XHiInt, ConstInt32Zero,
2607
+ ISD::CondCode::SETLT);
2608
+ } else {
2609
+ SDValue ConstIntZero = DAG.getConstant (0 , Loc, IVT);
2610
+ // Check if X is signed.
2611
+ // Bitcast X to an integer, and see if it is -(U)INT_MAX (compared to 0).
2612
+ SDValue XInt = DAG.getNode (ISD::BITCAST, Loc, IVT, X);
2613
+ IsXSigned = DAG.getSetCC (Loc, SetCCType, XInt, ConstIntZero,
2614
+ ISD::CondCode::SETLT);
2615
+ }
2616
+ // Return Y if X and Y are both zeroes and X == -0.0, if op is max;
2617
+ // Otherwise return Y.
2618
+ SDValue XOrY = IsMaxOp ? DAG.getSelect (Loc, VT, IsXSigned, Y, X)
2619
+ : DAG.getSelect (Loc, VT, IsXSigned, X, Y);
2620
+ MinMax = DAG.getSelect (Loc, VT, TstZeroes, XOrY, MinMax);
2621
+ }
2622
+ return MinMax;
2623
+ }
2624
+
2528
2625
SDValue MipsTargetLowering::
2529
2626
lowerFRAMEADDR (SDValue Op, SelectionDAG &DAG) const {
2530
2627
// check the depth
0 commit comments