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