[clang] [CIR][CodeGen] Upstream support for FP environments and options (PR #179121)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 1 09:38:28 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Ayokunle Amodu (ayokunle321)
<details>
<summary>Changes</summary>
This adds support for FP environment descriptions and options for scoped FP operations, i.e.,`CIRGenFPOptionsRAII`).
---
Full diff: https://github.com/llvm/llvm-project/pull/179121.diff
8 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+1)
- (added) clang/include/clang/CIR/Dialect/IR/FPEnv.h (+50)
- (modified) clang/include/clang/CIR/MissingFeatures.h (+7)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+56)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+70)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+15)
- (modified) clang/lib/CIR/Dialect/IR/CMakeLists.txt (+1)
- (added) clang/lib/CIR/Dialect/IR/FPEnv.cpp (+64)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c35c42c8c506b..770a6337626c4 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -14,6 +14,7 @@
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "clang/CIR/Dialect/IR/FPEnv.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/include/clang/CIR/Dialect/IR/FPEnv.h b/clang/include/clang/CIR/Dialect/IR/FPEnv.h
new file mode 100644
index 0000000000000..aceba9ee57d05
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/IR/FPEnv.h
@@ -0,0 +1,50 @@
+//===- FPEnv.h ---- FP Environment ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// This file contains the declarations of entities that describe floating
+/// point environment and related functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_DIALECT_IR_FPENV_H
+#define CLANG_CIR_DIALECT_IR_FPENV_H
+
+#include "llvm/ADT/FloatingPointMode.h"
+
+#include <optional>
+
+namespace cir {
+
+namespace fp {
+
+/// Exception behavior used for floating point operations.
+///
+/// Each of these values corresponds to some LLVMIR metadata argument value of a
+/// constrained floating point intrinsic. See the LLVM Language Reference Manual
+/// for details.
+enum ExceptionBehavior : uint8_t {
+ ebIgnore, ///< This corresponds to "fpexcept.ignore".
+ ebMayTrap, ///< This corresponds to "fpexcept.maytrap".
+ ebStrict, ///< This corresponds to "fpexcept.strict".
+};
+
+} // namespace fp
+
+/// For any RoundingMode enumerator, returns a string valid as input in
+/// constrained intrinsic rounding mode metadata.
+std::optional<llvm::StringRef> convertRoundingModeToStr(llvm::RoundingMode);
+
+/// For any ExceptionBehavior enumerator, returns a string valid as input in
+/// constrained intrinsic exception behavior metadata.
+std::optional<llvm::StringRef>
+ convertExceptionBehaviorToStr(fp::ExceptionBehavior);
+
+} // namespace cir
+
+#endif
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index cdd9fb950b8b2..c8e61fd217411 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -278,7 +278,14 @@ struct MissingFeatures {
static bool emitNullabilityCheck() { return false; }
static bool emitTypeCheck() { return false; }
static bool emitTypeMetadataCodeForVCall() { return false; }
+
+ // Fast math.
+ static bool fastMathGuard() { return false; }
+ // Should be implemented with a moduleOp level attribute and directly
+ // mapped to LLVM - those can be set directly for every relevant LLVM IR
+ // dialect operation (log10, ...).
static bool fastMathFlags() { return false; }
+ static bool fastMathFuncAttributes() { return false; }
static bool fpConstraints() { return false; }
static bool generateDebugInfo() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index dedb369bf3f67..812d9b9c39acf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -16,6 +16,7 @@
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/Support/LLVM.h"
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
+#include "clang/CIR/Dialect/IR/FPEnv.h"
#include "clang/CIR/MissingFeatures.h"
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
@@ -27,6 +28,10 @@ namespace clang::CIRGen {
class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
const CIRGenTypeCache &typeCache;
+ bool isFPConstrained = false;
+ cir::fp::ExceptionBehavior defaultConstrainedExcept = cir::fp::ebStrict;
+ llvm::RoundingMode defaultConstrainedRounding = llvm::RoundingMode::Dynamic;
+
llvm::StringMap<unsigned> recordNames;
llvm::StringMap<unsigned> globalsVersioning;
@@ -106,6 +111,57 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return baseName + "." + std::to_string(recordNames[baseName]++);
}
+ //
+ // Floating point specific helpers
+ // -------------------------------
+ //
+
+ /// Enable/Disable use of constrained floating point math. When enabled the
+ /// CreateF<op>() calls instead create constrained floating point intrinsic
+ /// calls. Fast math flags are unaffected by this setting.
+ void setIsFPConstrained(bool IsCon) {
+ if (IsCon)
+ llvm_unreachable("Constrained FP NYI");
+ isFPConstrained = IsCon;
+ }
+
+ /// Query for the use of constrained floating point math
+ bool getIsFPConstrained() {
+ if (isFPConstrained)
+ llvm_unreachable("Constrained FP NYI");
+ return isFPConstrained;
+ }
+
+ /// Set the exception handling to be used with constrained floating point
+ void setDefaultConstrainedExcept(cir::fp::ExceptionBehavior NewExcept) {
+#ifndef NDEBUG
+ std::optional<llvm::StringRef> ExceptStr =
+ cir::convertExceptionBehaviorToStr(NewExcept);
+ assert(ExceptStr && "Garbage strict exception behavior!");
+#endif
+ defaultConstrainedExcept = NewExcept;
+ }
+
+ /// Set the rounding mode handling to be used with constrained floating point
+ void setDefaultConstrainedRounding(llvm::RoundingMode NewRounding) {
+#ifndef NDEBUG
+ std::optional<llvm::StringRef> RoundingStr =
+ cir::convertRoundingModeToStr(NewRounding);
+ assert(RoundingStr && "Garbage strict rounding mode!");
+#endif
+ defaultConstrainedRounding = NewRounding;
+ }
+
+ /// Get the exception handling used with constrained floating point
+ cir::fp::ExceptionBehavior getDefaultConstrainedExcept() {
+ return defaultConstrainedExcept;
+ }
+
+ /// Get the rounding mode handling used with constrained floating point
+ llvm::RoundingMode getDefaultConstrainedRounding() {
+ return defaultConstrainedRounding;
+ }
+
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const {
if (&format == &llvm::APFloat::IEEEdouble())
return cir::LongDoubleType::get(getContext(), typeCache.doubleTy);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index f2d73720a9c2b..3f7a73115b886 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/GlobalDecl.h"
+#include "clang/CIR/Dialect/IR/FPEnv.h"
#include "clang/CIR/MissingFeatures.h"
#include <cassert>
@@ -956,6 +957,22 @@ LValue CIRGenFunction::makeNaturalAlignAddrLValue(mlir::Value val,
return makeAddrLValue(addr, ty, baseInfo);
}
+// Map the LangOption for exception behavior into the corresponding enum in
+// the IR.
+static cir::fp::ExceptionBehavior
+toConstrainedExceptMd(LangOptions::FPExceptionModeKind kind) {
+ switch (kind) {
+ case LangOptions::FPE_Ignore:
+ return cir::fp::ebIgnore;
+ case LangOptions::FPE_MayTrap:
+ return cir::fp::ebMayTrap;
+ case LangOptions::FPE_Strict:
+ return cir::fp::ebStrict;
+ default:
+ llvm_unreachable("Unsupported FP Exception Behavior");
+ }
+}
+
clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
FunctionArgList &args) {
const auto *fd = cast<FunctionDecl>(gd.getDecl());
@@ -1119,6 +1136,59 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
builder.createStore(loc, zeroValue, destPtr);
}
+CIRGenFunction::CIRGenFPOptionsRAII::CIRGenFPOptionsRAII(CIRGenFunction &cgf,
+ const clang::Expr *e)
+ : cgf(cgf) {
+ ConstructorHelper(e->getFPFeaturesInEffect(cgf.getLangOpts()));
+}
+
+CIRGenFunction::CIRGenFPOptionsRAII::CIRGenFPOptionsRAII(CIRGenFunction &cgf,
+ FPOptions fpFeatures)
+ : cgf(cgf) {
+ ConstructorHelper(fpFeatures);
+}
+
+void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
+ FPOptions fpFeatures) {
+ oldFPFeatures = cgf.curFPFeatures;
+ cgf.curFPFeatures = fpFeatures;
+
+ oldExcept = cgf.builder.getDefaultConstrainedExcept();
+ oldRounding =cgf.builder.getDefaultConstrainedRounding();
+
+ if (oldFPFeatures == fpFeatures)
+ return;
+
+ // TODO(cir): create guard to restore fast math configurations.
+ assert(!cir::MissingFeatures::fastMathGuard());
+
+ llvm::RoundingMode newRoundingBehavior = fpFeatures.getRoundingMode();
+ // TODO(cir): override rounding behaviour once FM configs are guarded.
+ auto newExceptionBehavior =
+ toConstrainedExceptMd(static_cast<LangOptions::FPExceptionModeKind>(
+ fpFeatures.getExceptionMode()));
+ // TODO(cir): override exception behaviour once FM configs are guarded.
+
+ // TODO(cir): override FP flags once FM configs are guarded.
+ assert(!cir::MissingFeatures::fastMathFlags());
+
+ assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() ||
+ isa<CXXConstructorDecl>(cgf.curFuncDecl) ||
+ isa<CXXDestructorDecl>(cgf.curFuncDecl) ||
+ (newExceptionBehavior == cir::fp::ebIgnore &&
+ newRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) &&
+ "FPConstrained should be enabled on entire function");
+
+ // TODO(cir): mark CIR function with fast math attributes.
+ assert(!cir::MissingFeatures::fastMathFuncAttributes());
+}
+
+CIRGenFunction::CIRGenFPOptionsRAII::~CIRGenFPOptionsRAII() {
+ cgf.curFPFeatures = oldFPFeatures;
+ cgf.builder.setDefaultConstrainedExcept(oldExcept);
+ cgf.builder.setDefaultConstrainedRounding(oldRounding);
+}
+
// TODO(cir): should be shared with LLVM codegen.
bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) {
const Expr *e = ce->getSubExpr();
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index adcf4d56e3892..01a36fca6c272 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -185,6 +185,21 @@ class CIRGenFunction : public CIRGenTypeCache {
/// Sanitizers enabled for this function.
clang::SanitizerSet sanOpts;
+ class CIRGenFPOptionsRAII {
+ public:
+ CIRGenFPOptionsRAII(CIRGenFunction &cgf, FPOptions FPFeatures);
+ CIRGenFPOptionsRAII(CIRGenFunction &cgf, const clang::Expr *E);
+ ~CIRGenFPOptionsRAII();
+
+ private:
+ void ConstructorHelper(clang::FPOptions FPFeatures);
+ CIRGenFunction &cgf;
+ clang::FPOptions oldFPFeatures;
+ cir::fp::ExceptionBehavior oldExcept;
+ llvm::RoundingMode oldRounding;
+ };
+ clang::FPOptions curFPFeatures;
+
/// The symbol table maps a variable name to a value in the current scope.
/// Entering a function creates a new scope, and the function arguments are
/// added to the mapping. When the processing of a function is terminated,
diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
index 98575941035f2..de3c7d7a1c3b9 100644
--- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(MLIRCIR
CIRMemorySlot.cpp
CIRTypes.cpp
CIRDataLayout.cpp
+ FPEnv.cpp
DEPENDS
MLIRCIROpsIncGen
diff --git a/clang/lib/CIR/Dialect/IR/FPEnv.cpp b/clang/lib/CIR/Dialect/IR/FPEnv.cpp
new file mode 100644
index 0000000000000..501268ce57f47
--- /dev/null
+++ b/clang/lib/CIR/Dialect/IR/FPEnv.cpp
@@ -0,0 +1,64 @@
+//===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// This file contains the implementations of entities that describe floating
+/// point environment.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/Dialect/IR/FPEnv.h"
+
+namespace cir {
+
+std::optional<llvm::StringRef>
+convertRoundingModeToStr(llvm::RoundingMode useRounding) {
+ std::optional<llvm::StringRef> roundingStr;
+ switch (useRounding) {
+ case llvm::RoundingMode::Dynamic:
+ roundingStr = "round.dynamic";
+ break;
+ case llvm::RoundingMode::NearestTiesToEven:
+ roundingStr = "round.tonearest";
+ break;
+ case llvm::RoundingMode::NearestTiesToAway:
+ roundingStr = "round.tonearestaway";
+ break;
+ case llvm::RoundingMode::TowardNegative:
+ roundingStr = "round.downward";
+ break;
+ case llvm::RoundingMode::TowardPositive:
+ roundingStr = "round.upward";
+ break;
+ case llvm::RoundingMode::TowardZero:
+ roundingStr = "round.towardZero";
+ break;
+ default:
+ break;
+ }
+ return roundingStr;
+}
+
+std::optional<llvm::StringRef>
+convertExceptionBehaviorToStr(fp::ExceptionBehavior useExcept) {
+ std::optional<llvm::StringRef> exceptStr;
+ switch (useExcept) {
+ case fp::ebStrict:
+ exceptStr = "fpexcept.strict";
+ break;
+ case fp::ebIgnore:
+ exceptStr = "fpexcept.ignore";
+ break;
+ case fp::ebMayTrap:
+ exceptStr = "fpexcept.maytrap";
+ break;
+ }
+ return exceptStr;
+}
+
+} // namespace cir
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/179121
More information about the cfe-commits
mailing list