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