[llvm] [NVPTX] Constant-folding for f2i, d2ui, f2ll etc. (PR #118965)

Alex MacLean via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 12 13:13:25 PST 2024


================
@@ -2300,6 +2360,211 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       return ConstantFP::get(Ty->getContext(), U);
     }
 
+    // NVVM float/double to signed/unsigned int32/int64 conversions:
+    switch (IntrinsicID) {
+    // f2i
+    case Intrinsic::nvvm_f2i_rm:
+    case Intrinsic::nvvm_f2i_rn:
+    case Intrinsic::nvvm_f2i_rp:
+    case Intrinsic::nvvm_f2i_rz:
+    case Intrinsic::nvvm_f2i_rm_ftz:
+    case Intrinsic::nvvm_f2i_rn_ftz:
+    case Intrinsic::nvvm_f2i_rp_ftz:
+    case Intrinsic::nvvm_f2i_rz_ftz:
+    // f2ui
+    case Intrinsic::nvvm_f2ui_rm:
+    case Intrinsic::nvvm_f2ui_rn:
+    case Intrinsic::nvvm_f2ui_rp:
+    case Intrinsic::nvvm_f2ui_rz:
+    case Intrinsic::nvvm_f2ui_rm_ftz:
+    case Intrinsic::nvvm_f2ui_rn_ftz:
+    case Intrinsic::nvvm_f2ui_rp_ftz:
+    case Intrinsic::nvvm_f2ui_rz_ftz:
+    // d2i
+    case Intrinsic::nvvm_d2i_rm:
+    case Intrinsic::nvvm_d2i_rn:
+    case Intrinsic::nvvm_d2i_rp:
+    case Intrinsic::nvvm_d2i_rz:
+    // d2ui
+    case Intrinsic::nvvm_d2ui_rm:
+    case Intrinsic::nvvm_d2ui_rn:
+    case Intrinsic::nvvm_d2ui_rp:
+    case Intrinsic::nvvm_d2ui_rz:
+    // f2ll
+    case Intrinsic::nvvm_f2ll_rm:
+    case Intrinsic::nvvm_f2ll_rn:
+    case Intrinsic::nvvm_f2ll_rp:
+    case Intrinsic::nvvm_f2ll_rz:
+    case Intrinsic::nvvm_f2ll_rm_ftz:
+    case Intrinsic::nvvm_f2ll_rn_ftz:
+    case Intrinsic::nvvm_f2ll_rp_ftz:
+    case Intrinsic::nvvm_f2ll_rz_ftz:
+    // f2ull
+    case Intrinsic::nvvm_f2ull_rm:
+    case Intrinsic::nvvm_f2ull_rn:
+    case Intrinsic::nvvm_f2ull_rp:
+    case Intrinsic::nvvm_f2ull_rz:
+    case Intrinsic::nvvm_f2ull_rm_ftz:
+    case Intrinsic::nvvm_f2ull_rn_ftz:
+    case Intrinsic::nvvm_f2ull_rp_ftz:
+    case Intrinsic::nvvm_f2ull_rz_ftz:
+    // d2ll
+    case Intrinsic::nvvm_d2ll_rm:
+    case Intrinsic::nvvm_d2ll_rn:
+    case Intrinsic::nvvm_d2ll_rp:
+    case Intrinsic::nvvm_d2ll_rz:
+    // d2ull
+    case Intrinsic::nvvm_d2ull_rm:
+    case Intrinsic::nvvm_d2ull_rn:
+    case Intrinsic::nvvm_d2ull_rp:
+    case Intrinsic::nvvm_d2ull_rz: {
+      // In float-to-integer conversion, NaN inputs are converted to 0.
+      if (U.isNaN())
+        return ConstantInt::get(Ty, 0);
+
+      APFloat::roundingMode RMode = APFloat::roundingMode::Invalid;
+      switch (IntrinsicID) {
+      // i_rm
+      case Intrinsic::nvvm_f2i_rm:
+      case Intrinsic::nvvm_f2ui_rm:
+      case Intrinsic::nvvm_f2i_rm_ftz:
+      case Intrinsic::nvvm_f2ui_rm_ftz:
+      case Intrinsic::nvvm_d2i_rm:
+      case Intrinsic::nvvm_d2ui_rm:
+      // ll_rm
+      case Intrinsic::nvvm_f2ll_rm:
+      case Intrinsic::nvvm_f2ull_rm:
+      case Intrinsic::nvvm_f2ll_rm_ftz:
+      case Intrinsic::nvvm_f2ull_rm_ftz:
+      case Intrinsic::nvvm_d2ll_rm:
+      case Intrinsic::nvvm_d2ull_rm:
+        RMode = APFloat::rmTowardNegative;
+        break;
+
+      // i_rn
+      case Intrinsic::nvvm_f2i_rn:
+      case Intrinsic::nvvm_f2ui_rn:
+      case Intrinsic::nvvm_f2i_rn_ftz:
+      case Intrinsic::nvvm_f2ui_rn_ftz:
+      case Intrinsic::nvvm_d2i_rn:
+      case Intrinsic::nvvm_d2ui_rn:
+      // ll_rn
+      case Intrinsic::nvvm_f2ll_rn:
+      case Intrinsic::nvvm_f2ull_rn:
+      case Intrinsic::nvvm_f2ll_rn_ftz:
+      case Intrinsic::nvvm_f2ull_rn_ftz:
+      case Intrinsic::nvvm_d2ll_rn:
+      case Intrinsic::nvvm_d2ull_rn:
+        RMode = APFloat::rmNearestTiesToEven;
+        break;
+
+      // i_rp
+      case Intrinsic::nvvm_f2i_rp:
+      case Intrinsic::nvvm_f2ui_rp:
+      case Intrinsic::nvvm_f2i_rp_ftz:
+      case Intrinsic::nvvm_f2ui_rp_ftz:
+      case Intrinsic::nvvm_d2i_rp:
+      case Intrinsic::nvvm_d2ui_rp:
+      // ll_rp
+      case Intrinsic::nvvm_f2ll_rp:
+      case Intrinsic::nvvm_f2ull_rp:
+      case Intrinsic::nvvm_f2ll_rp_ftz:
+      case Intrinsic::nvvm_f2ull_rp_ftz:
+      case Intrinsic::nvvm_d2ll_rp:
+      case Intrinsic::nvvm_d2ull_rp:
+        RMode = APFloat::rmTowardPositive;
+        break;
+
+      // i_rz
+      case Intrinsic::nvvm_f2i_rz:
+      case Intrinsic::nvvm_f2ui_rz:
+      case Intrinsic::nvvm_f2i_rz_ftz:
+      case Intrinsic::nvvm_f2ui_rz_ftz:
+      case Intrinsic::nvvm_d2i_rz:
+      case Intrinsic::nvvm_d2ui_rz:
+      // ll_rz
+      case Intrinsic::nvvm_f2ll_rz:
+      case Intrinsic::nvvm_f2ull_rz:
+      case Intrinsic::nvvm_f2ll_rz_ftz:
+      case Intrinsic::nvvm_f2ull_rz_ftz:
+      case Intrinsic::nvvm_d2ll_rz:
+      case Intrinsic::nvvm_d2ull_rz:
+        RMode = APFloat::rmTowardZero;
+        break;
+      default:
+        llvm_unreachable("Invalid f2i/d2i rounding mode intrinsic");
+      }
+      assert(RM != APFloat::roundingMode::Invalid);
+
+      bool IsFTZ = false;
+      switch (IntrinsicID) {
+      case Intrinsic::nvvm_f2i_rm_ftz:
+      case Intrinsic::nvvm_f2i_rn_ftz:
+      case Intrinsic::nvvm_f2i_rp_ftz:
+      case Intrinsic::nvvm_f2i_rz_ftz:
+      case Intrinsic::nvvm_f2ui_rm_ftz:
+      case Intrinsic::nvvm_f2ui_rn_ftz:
+      case Intrinsic::nvvm_f2ui_rp_ftz:
+      case Intrinsic::nvvm_f2ui_rz_ftz:
+      case Intrinsic::nvvm_f2ll_rm_ftz:
+      case Intrinsic::nvvm_f2ll_rn_ftz:
+      case Intrinsic::nvvm_f2ll_rp_ftz:
+      case Intrinsic::nvvm_f2ll_rz_ftz:
+      case Intrinsic::nvvm_f2ull_rm_ftz:
+      case Intrinsic::nvvm_f2ull_rn_ftz:
+      case Intrinsic::nvvm_f2ull_rp_ftz:
+      case Intrinsic::nvvm_f2ull_rz_ftz:
+        IsFTZ = true;
+        break;
+      }
+
+      bool IsSigned = false;
+      switch (IntrinsicID) {
+      // f2i
+      case Intrinsic::nvvm_f2i_rm:
+      case Intrinsic::nvvm_f2i_rm_ftz:
+      case Intrinsic::nvvm_f2i_rn:
+      case Intrinsic::nvvm_f2i_rn_ftz:
+      case Intrinsic::nvvm_f2i_rp:
+      case Intrinsic::nvvm_f2i_rp_ftz:
+      case Intrinsic::nvvm_f2i_rz:
+      case Intrinsic::nvvm_f2i_rz_ftz:
+      // d2i
+      case Intrinsic::nvvm_d2i_rm:
+      case Intrinsic::nvvm_d2i_rn:
+      case Intrinsic::nvvm_d2i_rp:
+      case Intrinsic::nvvm_d2i_rz:
+      // f2ll
+      case Intrinsic::nvvm_f2ll_rm:
+      case Intrinsic::nvvm_f2ll_rm_ftz:
+      case Intrinsic::nvvm_f2ll_rn:
+      case Intrinsic::nvvm_f2ll_rn_ftz:
+      case Intrinsic::nvvm_f2ll_rp:
+      case Intrinsic::nvvm_f2ll_rp_ftz:
+      case Intrinsic::nvvm_f2ll_rz:
+      case Intrinsic::nvvm_f2ll_rz_ftz:
+      // d2ll
+      case Intrinsic::nvvm_d2ll_rm:
+      case Intrinsic::nvvm_d2ll_rn:
+      case Intrinsic::nvvm_d2ll_rp:
+      case Intrinsic::nvvm_d2ll_rz:
+        IsSigned = true;
+        break;
+      }
+
+      APSInt ResInt(Ty->getIntegerBitWidth(), !IsSigned);
+      auto FloatToRound = IsFTZ ? FTZPreserveSign(Op->getType(), U) : U;
+
+      bool IsExact = false;
+      APFloat::opStatus Status =
+          FloatToRound.convertToInteger(ResInt, RMode, &IsExact);
+
+      if (Status != APFloat::opInvalidOp)
----------------
AlexMaclean wrote:

When might `APFloat::opInvalidOp` be returned?

https://github.com/llvm/llvm-project/pull/118965


More information about the llvm-commits mailing list