[flang-commits] [flang] [flang] Respect math flags during conversions (PR #214311)

via flang-commits flang-commits at lists.llvm.org
Wed Aug 5 11:52:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: jon-gibney

<details>
<summary>Changes</summary>

We normally use saturating intrinsics when converting from fp to integers, but when running with -ffast-math we can just use fptosi/fptoui, which avoids generating expensive overflow/NAN checks.

Assisted-by: Claude Opus

---
Full diff: https://github.com/llvm/llvm-project/pull/214311.diff


4 Files Affected:

- (modified) flang/include/flang/Optimizer/CodeGen/CodeGen.h (+2) 
- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+24-12) 
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (+1) 
- (added) flang/test/Integration/unsafe-fp-conversion.f90 (+47) 


``````````diff
diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
index b7a9397edfe6d..283b7226b6e3c 100644
--- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h
+++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
@@ -65,6 +65,8 @@ struct FIRToLLVMPassOptions {
   // Conversion pass of the MLIR complex dialect.
   Fortran::frontend::CodeGenOptions::ComplexRangeKind ComplexRange =
       Fortran::frontend::CodeGenOptions::ComplexRangeKind::CX_Full;
+
+  bool unsafeFPConversion = false;
 };
 
 /// Convert FIR to the LLVM IR dialect with default options.
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 55c6afee45996..4ebffa0f3797f 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1134,19 +1134,31 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
         return mlir::success();
       }
       if (mlir::isa<mlir::IntegerType>(toTy)) {
-        // NOTE: We are checking the fir type here because toTy is an LLVM type
-        // which is signless, and we need to use the intrinsic that matches the
-        // sign of the output in fir.
-        if (toFirTy.isUnsignedInteger()) {
-          auto intrinsicName =
-              mlir::StringAttr::get(convert.getContext(), "llvm.fptoui.sat");
-          rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
-              convert, toTy, intrinsicName, op0);
+        if (options.unsafeFPConversion) {
+          // Under unsafe FP math (e.g. -ffast-math), use plain fptosi/fptoui
+          // instead of saturating intrinsics. This avoids expensive
+          // overflow/NAN checking in the generated code.
+          mlir::Value res;
+          if (toFirTy.isUnsignedInteger())
+            res = mlir::LLVM::FPToUIOp::create(rewriter, loc, toTy, op0);
+          else
+            res = mlir::LLVM::FPToSIOp::create(rewriter, loc, toTy, op0);
+          rewriter.replaceOp(convert, res);
         } else {
-          auto intrinsicName =
-              mlir::StringAttr::get(convert.getContext(), "llvm.fptosi.sat");
-          rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
-              convert, toTy, intrinsicName, op0);
+          // NOTE: We are checking the fir type here because toTy is an LLVM
+          // type which is signless, and we need to use the intrinsic that
+          // matches the sign of the output in fir.
+          if (toFirTy.isUnsignedInteger()) {
+            auto intrinsicName =
+                mlir::StringAttr::get(convert.getContext(), "llvm.fptoui.sat");
+            rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
+                convert, toTy, intrinsicName, op0);
+          } else {
+            auto intrinsicName =
+                mlir::StringAttr::get(convert.getContext(), "llvm.fptosi.sat");
+            rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
+                convert, toTy, intrinsicName, op0);
+          }
         }
         return mlir::success();
       }
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 15a342e10fc7f..c866f0a76ccb2 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -112,6 +112,7 @@ getFIRToLLVMPassOptions(const MLIRToLLVMPassPipelineConfig &config) {
   options.typeDescriptorsRenamedForAssembly =
       !disableCompilerGeneratedNamesConversion;
   options.ComplexRange = config.ComplexRange;
+  options.unsafeFPConversion = config.UnsafeFPMath;
   return options;
 }
 
diff --git a/flang/test/Integration/unsafe-fp-conversion.f90 b/flang/test/Integration/unsafe-fp-conversion.f90
new file mode 100644
index 0000000000000..ec173584bd5ed
--- /dev/null
+++ b/flang/test/Integration/unsafe-fp-conversion.f90
@@ -0,0 +1,47 @@
+! Test that -ffast-math uses plain fptosi/fptoui for float-to-integer
+! conversions instead of the saturating intrinsics (llvm.fptosi.sat /
+! llvm.fptoui.sat).
+
+! RUN: %flang -O2 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=SAFE
+! RUN: %flang -O2 -ffast-math -S -emit-llvm %s -o - | FileCheck %s --check-prefix=FAST
+
+! SAFE-LABEL: define {{.*}} @float_to_int_
+! SAFE: call i32 @llvm.fptosi.sat.i32.f32
+! SAFE-NOT: fptosi float
+
+! FAST-LABEL: define {{.*}} @float_to_int_
+! FAST: fptosi float
+! FAST-NOT: llvm.fptosi.sat
+
+subroutine float_to_int(x, i)
+  real, intent(in) :: x
+  integer, intent(out) :: i
+  i = x
+end subroutine
+
+! SAFE-LABEL: define {{.*}} @double_to_int_
+! SAFE: call i32 @llvm.fptosi.sat.i32.f64
+! SAFE-NOT: fptosi double
+
+! FAST-LABEL: define {{.*}} @double_to_int_
+! FAST: fptosi double
+! FAST-NOT: llvm.fptosi.sat
+
+subroutine double_to_int(d, i)
+  double precision, intent(in) :: d
+  integer, intent(out) :: i
+  i = d
+end subroutine
+
+! SAFE-LABEL: define {{.*}} @float_to_int8_
+! SAFE: call i64 @llvm.fptosi.sat.i64.f32
+
+! FAST-LABEL: define {{.*}} @float_to_int8_
+! FAST: fptosi float
+! FAST-NOT: llvm.fptosi.sat
+
+subroutine float_to_int8(x, i)
+  real, intent(in) :: x
+  integer(8), intent(out) :: i
+  i = x
+end subroutine

``````````

</details>


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


More information about the flang-commits mailing list