https://github.com/ayokunle321 updated https://github.com/llvm/llvm-project/pull/179121
>From 2d0750305d206ef1e63e4ed46b039240441dd9a3 Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Sun, 1 Feb 2026 10:20:54 -0700 Subject: [PATCH 1/2] add support for cgFPOptionsRAII --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 1 + clang/include/clang/CIR/Dialect/IR/FPEnv.h | 50 +++++++++++++ clang/include/clang/CIR/MissingFeatures.h | 7 ++ clang/lib/CIR/CodeGen/CIRGenBuilder.h | 56 +++++++++++++++ clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 70 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenFunction.h | 15 ++++ clang/lib/CIR/Dialect/IR/CMakeLists.txt | 1 + clang/lib/CIR/Dialect/IR/FPEnv.cpp | 64 +++++++++++++++++ 8 files changed, 264 insertions(+) create mode 100644 clang/include/clang/CIR/Dialect/IR/FPEnv.h create mode 100644 clang/lib/CIR/Dialect/IR/FPEnv.cpp 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 >From 1a0af4e5982b8116b6679c4dddbd0e865c0e21de Mon Sep 17 00:00:00 2001 From: Ayokunle Amodu <[email protected]> Date: Sun, 1 Feb 2026 10:44:30 -0700 Subject: [PATCH 2/2] fix code format --- clang/include/clang/CIR/MissingFeatures.h | 2 +- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index c8e61fd217411..19cc7a88d1040 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -278,7 +278,7 @@ 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 diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 3f7a73115b886..e9e6ac74720f0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -1154,7 +1154,7 @@ void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper( cgf.curFPFeatures = fpFeatures; oldExcept = cgf.builder.getDefaultConstrainedExcept(); - oldRounding =cgf.builder.getDefaultConstrainedRounding(); + oldRounding = cgf.builder.getDefaultConstrainedRounding(); if (oldFPFeatures == fpFeatures) return; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
