[clang] 260f6fe - [CIR][NFC] Upstream support for FP environments and RAII options (#179121)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 17 16:10:31 PST 2026
Author: Ayokunle Amodu
Date: 2026-02-17T16:10:26-08:00
New Revision: 260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea
URL: https://github.com/llvm/llvm-project/commit/260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea
DIFF: https://github.com/llvm/llvm-project/commit/260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea.diff
LOG: [CIR][NFC] Upstream support for FP environments and RAII options (#179121)
This adds support for FP environment descriptions and RAII options for
FP operations, i.e.,`CIRGenFPOptionsRAII`).
Added:
Modified:
clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
clang/include/clang/CIR/MissingFeatures.h
clang/lib/CIR/CodeGen/CIRGenBuilder.h
clang/lib/CIR/CodeGen/CIRGenFunction.cpp
clang/lib/CIR/CodeGen/CIRGenFunction.h
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 19de9b120887a..dd9dc7f0fe0f5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -16,6 +16,7 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/IR/FPEnv.h"
#include "llvm/Support/ErrorHandling.h"
#include "mlir/IR/Builders.h"
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 1e9b4f425cec5..59d0482d37f15 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -279,7 +279,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 debd2faa29ef3..cd13c9578adf7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -22,11 +22,16 @@
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/FPEnv.h"
namespace clang::CIRGen {
class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
const CIRGenTypeCache &typeCache;
+ bool isFPConstrained = false;
+ llvm::fp::ExceptionBehavior defaultConstrainedExcept = llvm::fp::ebStrict;
+ llvm::RoundingMode defaultConstrainedRounding = llvm::RoundingMode::Dynamic;
+
llvm::StringMap<unsigned> recordNames;
llvm::StringMap<unsigned> globalsVersioning;
@@ -106,6 +111,43 @@ 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) { isFPConstrained = isCon; }
+
+ /// Query for the use of constrained floating point math
+ bool getIsFPConstrained() const { return isFPConstrained; }
+
+ /// Set the exception handling to be used with constrained floating point
+ void setDefaultConstrainedExcept(llvm::fp::ExceptionBehavior newExcept) {
+ assert(llvm::convertExceptionBehaviorToStr(newExcept) &&
+ "Garbage strict exception behavior!");
+ defaultConstrainedExcept = newExcept;
+ }
+
+ /// Get the exception handling used with constrained floating point
+ llvm::fp::ExceptionBehavior getDefaultConstrainedExcept() const {
+ return defaultConstrainedExcept;
+ }
+
+ /// Set the rounding mode handling to be used with constrained floating point
+ void setDefaultConstrainedRounding(llvm::RoundingMode newRounding) {
+ assert(llvm::convertRoundingModeToStr(newRounding) &&
+ "Garbage strict rounding mode!");
+ defaultConstrainedRounding = newRounding;
+ }
+
+ /// Get the rounding mode handling used with constrained floating point
+ llvm::RoundingMode getDefaultConstrainedRounding() const {
+ 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 c900797e54c81..f8f674c4d2c21 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/CIR/MissingFeatures.h"
+#include "llvm/IR/FPEnv.h"
#include <cassert>
@@ -956,6 +957,23 @@ 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 llvm::fp::ExceptionBehavior
+toConstrainedExceptMd(LangOptions::FPExceptionModeKind kind) {
+ switch (kind) {
+ case LangOptions::FPE_Ignore:
+ return llvm::fp::ebIgnore;
+ case LangOptions::FPE_MayTrap:
+ return llvm::fp::ebMayTrap;
+ case LangOptions::FPE_Strict:
+ return llvm::fp::ebStrict;
+ case LangOptions::FPE_Default:
+ llvm_unreachable("expected explicitly initialized exception behavior");
+ }
+ llvm_unreachable("unsupported FP exception behavior");
+}
+
clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
FunctionArgList &args) {
const auto *fd = cast<FunctionDecl>(gd.getDecl());
@@ -1119,6 +1137,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.
+ llvm::fp::ExceptionBehavior 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 == llvm::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 cc0087ba2d6bd..a21697ef8f1d4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -186,6 +186,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;
+ llvm::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,
More information about the cfe-commits
mailing list