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