@@ -291,6 +291,143 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
291291 return ConstantVector::get (Result);
292292}
293293
294+ // ===----------------------------------------------------------------------===//
295+ // NVVM-specific internal helper functions
296+ // ===----------------------------------------------------------------------===//
297+
298+ static bool NVVMIntrinsicShouldFTZ (Intrinsic::ID IntrinsicID) {
299+ switch (IntrinsicID) {
300+ // Float to i32 / i64 conversion intrinsics:
301+ case Intrinsic::nvvm_f2i_rm_ftz:
302+ case Intrinsic::nvvm_f2i_rn_ftz:
303+ case Intrinsic::nvvm_f2i_rp_ftz:
304+ case Intrinsic::nvvm_f2i_rz_ftz:
305+
306+ case Intrinsic::nvvm_f2ui_rm_ftz:
307+ case Intrinsic::nvvm_f2ui_rn_ftz:
308+ case Intrinsic::nvvm_f2ui_rp_ftz:
309+ case Intrinsic::nvvm_f2ui_rz_ftz:
310+
311+ case Intrinsic::nvvm_f2ll_rm_ftz:
312+ case Intrinsic::nvvm_f2ll_rn_ftz:
313+ case Intrinsic::nvvm_f2ll_rp_ftz:
314+ case Intrinsic::nvvm_f2ll_rz_ftz:
315+
316+ case Intrinsic::nvvm_f2ull_rm_ftz:
317+ case Intrinsic::nvvm_f2ull_rn_ftz:
318+ case Intrinsic::nvvm_f2ull_rp_ftz:
319+ case Intrinsic::nvvm_f2ull_rz_ftz:
320+ return true ;
321+ }
322+ return false ;
323+ }
324+
325+ static bool NVVMIntrinsicConvertsToSignedInteger (Intrinsic::ID IntrinsicID) {
326+ switch (IntrinsicID) {
327+ // f2i
328+ case Intrinsic::nvvm_f2i_rm:
329+ case Intrinsic::nvvm_f2i_rm_ftz:
330+ case Intrinsic::nvvm_f2i_rn:
331+ case Intrinsic::nvvm_f2i_rn_ftz:
332+ case Intrinsic::nvvm_f2i_rp:
333+ case Intrinsic::nvvm_f2i_rp_ftz:
334+ case Intrinsic::nvvm_f2i_rz:
335+ case Intrinsic::nvvm_f2i_rz_ftz:
336+ // d2i
337+ case Intrinsic::nvvm_d2i_rm:
338+ case Intrinsic::nvvm_d2i_rn:
339+ case Intrinsic::nvvm_d2i_rp:
340+ case Intrinsic::nvvm_d2i_rz:
341+ // f2ll
342+ case Intrinsic::nvvm_f2ll_rm:
343+ case Intrinsic::nvvm_f2ll_rm_ftz:
344+ case Intrinsic::nvvm_f2ll_rn:
345+ case Intrinsic::nvvm_f2ll_rn_ftz:
346+ case Intrinsic::nvvm_f2ll_rp:
347+ case Intrinsic::nvvm_f2ll_rp_ftz:
348+ case Intrinsic::nvvm_f2ll_rz:
349+ case Intrinsic::nvvm_f2ll_rz_ftz:
350+ // d2ll
351+ case Intrinsic::nvvm_d2ll_rm:
352+ case Intrinsic::nvvm_d2ll_rn:
353+ case Intrinsic::nvvm_d2ll_rp:
354+ case Intrinsic::nvvm_d2ll_rz:
355+ return true ;
356+ }
357+ return false ;
358+ }
359+
360+ static APFloat::roundingMode
361+ NVVMIntrinsicGetRoundingMode (Intrinsic::ID IntrinsicID) {
362+ switch (IntrinsicID) {
363+ // RM:
364+ case Intrinsic::nvvm_f2i_rm:
365+ case Intrinsic::nvvm_f2ui_rm:
366+ case Intrinsic::nvvm_f2i_rm_ftz:
367+ case Intrinsic::nvvm_f2ui_rm_ftz:
368+ case Intrinsic::nvvm_d2i_rm:
369+ case Intrinsic::nvvm_d2ui_rm:
370+
371+ case Intrinsic::nvvm_f2ll_rm:
372+ case Intrinsic::nvvm_f2ull_rm:
373+ case Intrinsic::nvvm_f2ll_rm_ftz:
374+ case Intrinsic::nvvm_f2ull_rm_ftz:
375+ case Intrinsic::nvvm_d2ll_rm:
376+ case Intrinsic::nvvm_d2ull_rm:
377+ return APFloat::rmTowardNegative;
378+
379+ // RN:
380+ case Intrinsic::nvvm_f2i_rn:
381+ case Intrinsic::nvvm_f2ui_rn:
382+ case Intrinsic::nvvm_f2i_rn_ftz:
383+ case Intrinsic::nvvm_f2ui_rn_ftz:
384+ case Intrinsic::nvvm_d2i_rn:
385+ case Intrinsic::nvvm_d2ui_rn:
386+
387+ case Intrinsic::nvvm_f2ll_rn:
388+ case Intrinsic::nvvm_f2ull_rn:
389+ case Intrinsic::nvvm_f2ll_rn_ftz:
390+ case Intrinsic::nvvm_f2ull_rn_ftz:
391+ case Intrinsic::nvvm_d2ll_rn:
392+ case Intrinsic::nvvm_d2ull_rn:
393+ return APFloat::rmNearestTiesToEven;
394+
395+ // RP:
396+ case Intrinsic::nvvm_f2i_rp:
397+ case Intrinsic::nvvm_f2ui_rp:
398+ case Intrinsic::nvvm_f2i_rp_ftz:
399+ case Intrinsic::nvvm_f2ui_rp_ftz:
400+ case Intrinsic::nvvm_d2i_rp:
401+ case Intrinsic::nvvm_d2ui_rp:
402+
403+ case Intrinsic::nvvm_f2ll_rp:
404+ case Intrinsic::nvvm_f2ull_rp:
405+ case Intrinsic::nvvm_f2ll_rp_ftz:
406+ case Intrinsic::nvvm_f2ull_rp_ftz:
407+ case Intrinsic::nvvm_d2ll_rp:
408+ case Intrinsic::nvvm_d2ull_rp:
409+ return APFloat::rmTowardPositive;
410+
411+ // RZ:
412+ case Intrinsic::nvvm_f2i_rz:
413+ case Intrinsic::nvvm_f2ui_rz:
414+ case Intrinsic::nvvm_f2i_rz_ftz:
415+ case Intrinsic::nvvm_f2ui_rz_ftz:
416+ case Intrinsic::nvvm_d2i_rz:
417+ case Intrinsic::nvvm_d2ui_rz:
418+
419+ case Intrinsic::nvvm_f2ll_rz:
420+ case Intrinsic::nvvm_f2ull_rz:
421+ case Intrinsic::nvvm_f2ll_rz_ftz:
422+ case Intrinsic::nvvm_f2ull_rz_ftz:
423+ case Intrinsic::nvvm_d2ll_rz:
424+ case Intrinsic::nvvm_d2ull_rz:
425+ return APFloat::rmTowardZero;
426+ }
427+ llvm_unreachable (" Invalid f2i/d2i rounding mode intrinsic" );
428+ return APFloat::roundingMode::Invalid;
429+ }
430+
294431} // end anonymous namespace
295432
296433// / If this constant is a constant offset from a global, return the global and
@@ -1902,10 +2039,9 @@ inline bool llvm_fenv_testexcept() {
19022039 return false ;
19032040}
19042041
1905- static const APFloat FTZPreserveSign (Type *Ty, const APFloat &V) {
2042+ static const APFloat FTZPreserveSign (const APFloat &V) {
19062043 if (V.isDenormal ())
1907- return APFloat::getZero (Ty->getFltSemantics (), V.isNegative ());
1908-
2044+ return APFloat::getZero (V.getSemantics (), V.isNegative ());
19092045 return V;
19102046}
19112047
@@ -2431,138 +2567,14 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
24312567 if (U.isNaN ())
24322568 return ConstantInt::get (Ty, 0 );
24332569
2434- APFloat::roundingMode RMode = APFloat::roundingMode::Invalid;
2435- switch (IntrinsicID) {
2436- // i_rm
2437- case Intrinsic::nvvm_f2i_rm:
2438- case Intrinsic::nvvm_f2ui_rm:
2439- case Intrinsic::nvvm_f2i_rm_ftz:
2440- case Intrinsic::nvvm_f2ui_rm_ftz:
2441- case Intrinsic::nvvm_d2i_rm:
2442- case Intrinsic::nvvm_d2ui_rm:
2443- // ll_rm
2444- case Intrinsic::nvvm_f2ll_rm:
2445- case Intrinsic::nvvm_f2ull_rm:
2446- case Intrinsic::nvvm_f2ll_rm_ftz:
2447- case Intrinsic::nvvm_f2ull_rm_ftz:
2448- case Intrinsic::nvvm_d2ll_rm:
2449- case Intrinsic::nvvm_d2ull_rm:
2450- RMode = APFloat::rmTowardNegative;
2451- break ;
2452-
2453- // i_rn
2454- case Intrinsic::nvvm_f2i_rn:
2455- case Intrinsic::nvvm_f2ui_rn:
2456- case Intrinsic::nvvm_f2i_rn_ftz:
2457- case Intrinsic::nvvm_f2ui_rn_ftz:
2458- case Intrinsic::nvvm_d2i_rn:
2459- case Intrinsic::nvvm_d2ui_rn:
2460- // ll_rn
2461- case Intrinsic::nvvm_f2ll_rn:
2462- case Intrinsic::nvvm_f2ull_rn:
2463- case Intrinsic::nvvm_f2ll_rn_ftz:
2464- case Intrinsic::nvvm_f2ull_rn_ftz:
2465- case Intrinsic::nvvm_d2ll_rn:
2466- case Intrinsic::nvvm_d2ull_rn:
2467- RMode = APFloat::rmNearestTiesToEven;
2468- break ;
2469-
2470- // i_rp
2471- case Intrinsic::nvvm_f2i_rp:
2472- case Intrinsic::nvvm_f2ui_rp:
2473- case Intrinsic::nvvm_f2i_rp_ftz:
2474- case Intrinsic::nvvm_f2ui_rp_ftz:
2475- case Intrinsic::nvvm_d2i_rp:
2476- case Intrinsic::nvvm_d2ui_rp:
2477- // ll_rp
2478- case Intrinsic::nvvm_f2ll_rp:
2479- case Intrinsic::nvvm_f2ull_rp:
2480- case Intrinsic::nvvm_f2ll_rp_ftz:
2481- case Intrinsic::nvvm_f2ull_rp_ftz:
2482- case Intrinsic::nvvm_d2ll_rp:
2483- case Intrinsic::nvvm_d2ull_rp:
2484- RMode = APFloat::rmTowardPositive;
2485- break ;
2486-
2487- // i_rz
2488- case Intrinsic::nvvm_f2i_rz:
2489- case Intrinsic::nvvm_f2ui_rz:
2490- case Intrinsic::nvvm_f2i_rz_ftz:
2491- case Intrinsic::nvvm_f2ui_rz_ftz:
2492- case Intrinsic::nvvm_d2i_rz:
2493- case Intrinsic::nvvm_d2ui_rz:
2494- // ll_rz
2495- case Intrinsic::nvvm_f2ll_rz:
2496- case Intrinsic::nvvm_f2ull_rz:
2497- case Intrinsic::nvvm_f2ll_rz_ftz:
2498- case Intrinsic::nvvm_f2ull_rz_ftz:
2499- case Intrinsic::nvvm_d2ll_rz:
2500- case Intrinsic::nvvm_d2ull_rz:
2501- RMode = APFloat::rmTowardZero;
2502- break ;
2503- default :
2504- llvm_unreachable (" Invalid f2i/d2i rounding mode intrinsic" );
2505- }
2570+ APFloat::roundingMode RMode = NVVMIntrinsicGetRoundingMode (IntrinsicID);
25062571 assert (RM != APFloat::roundingMode::Invalid);
25072572
2508- bool IsFTZ = false ;
2509- switch (IntrinsicID) {
2510- case Intrinsic::nvvm_f2i_rm_ftz:
2511- case Intrinsic::nvvm_f2i_rn_ftz:
2512- case Intrinsic::nvvm_f2i_rp_ftz:
2513- case Intrinsic::nvvm_f2i_rz_ftz:
2514- case Intrinsic::nvvm_f2ui_rm_ftz:
2515- case Intrinsic::nvvm_f2ui_rn_ftz:
2516- case Intrinsic::nvvm_f2ui_rp_ftz:
2517- case Intrinsic::nvvm_f2ui_rz_ftz:
2518- case Intrinsic::nvvm_f2ll_rm_ftz:
2519- case Intrinsic::nvvm_f2ll_rn_ftz:
2520- case Intrinsic::nvvm_f2ll_rp_ftz:
2521- case Intrinsic::nvvm_f2ll_rz_ftz:
2522- case Intrinsic::nvvm_f2ull_rm_ftz:
2523- case Intrinsic::nvvm_f2ull_rn_ftz:
2524- case Intrinsic::nvvm_f2ull_rp_ftz:
2525- case Intrinsic::nvvm_f2ull_rz_ftz:
2526- IsFTZ = true ;
2527- break ;
2528- }
2529-
2530- bool IsSigned = false ;
2531- switch (IntrinsicID) {
2532- // f2i
2533- case Intrinsic::nvvm_f2i_rm:
2534- case Intrinsic::nvvm_f2i_rm_ftz:
2535- case Intrinsic::nvvm_f2i_rn:
2536- case Intrinsic::nvvm_f2i_rn_ftz:
2537- case Intrinsic::nvvm_f2i_rp:
2538- case Intrinsic::nvvm_f2i_rp_ftz:
2539- case Intrinsic::nvvm_f2i_rz:
2540- case Intrinsic::nvvm_f2i_rz_ftz:
2541- // d2i
2542- case Intrinsic::nvvm_d2i_rm:
2543- case Intrinsic::nvvm_d2i_rn:
2544- case Intrinsic::nvvm_d2i_rp:
2545- case Intrinsic::nvvm_d2i_rz:
2546- // f2ll
2547- case Intrinsic::nvvm_f2ll_rm:
2548- case Intrinsic::nvvm_f2ll_rm_ftz:
2549- case Intrinsic::nvvm_f2ll_rn:
2550- case Intrinsic::nvvm_f2ll_rn_ftz:
2551- case Intrinsic::nvvm_f2ll_rp:
2552- case Intrinsic::nvvm_f2ll_rp_ftz:
2553- case Intrinsic::nvvm_f2ll_rz:
2554- case Intrinsic::nvvm_f2ll_rz_ftz:
2555- // d2ll
2556- case Intrinsic::nvvm_d2ll_rm:
2557- case Intrinsic::nvvm_d2ll_rn:
2558- case Intrinsic::nvvm_d2ll_rp:
2559- case Intrinsic::nvvm_d2ll_rz:
2560- IsSigned = true ;
2561- break ;
2562- }
2573+ bool IsFTZ = NVVMIntrinsicShouldFTZ (IntrinsicID);
2574+ bool IsSigned = NVVMIntrinsicConvertsToSignedInteger (IntrinsicID);
25632575
25642576 APSInt ResInt (Ty->getIntegerBitWidth (), !IsSigned);
2565- auto FloatToRound = IsFTZ ? FTZPreserveSign (Op-> getType (), U) : U;
2577+ auto FloatToRound = IsFTZ ? FTZPreserveSign (U) : U;
25662578
25672579 bool IsExact = false ;
25682580 APFloat::opStatus Status =
0 commit comments